library(xlsx);library(dplyr);library(lubridate)
options(scipen=999) #remove scientific notation
data <- read.csv2("taux_utilisation_actes.csv")
data_eat <- data[data$eat == "Oui",]
data_eat

Global variables

#window size
max.window.size <- 5 #size of the window = number of collaborative acts per window
max.window.size
[1] 5
#dyad having used the emotion awareness tool (eat condition) for sharing their emotions 
dyads_eat <- c(
"D02",
"D05",
"D07",
"D09",
"D13",
"D16",
"D21",
"D23",
"D26",
"D27",
"D29")

#participants in eat condition
participants_eat <- c(
"D02P01",
"D02P02",
"D05P01",
"D05P02",
"D07P01",
"D07P02",
"D09P01",
"D09P02",
"D13P01",
"D13P02",
"D16P01",
"D16P02",
"D21P01",
"D21P02",
"D23P01",
"D23P02",
"D26P01",
"D26P02",
"D27P01",
"D27P02",
"D29P01",
"D29P02")

#participants in no-eat condition
participants_no_eat <- c(
"D04P01",
"D04P02",
"D06P01",
"D06P02",
"D08P01",
"D08P02",
"D10P01",
"D10P02",
"D12P01",
"D12P02",
"D15P01",
"D15P02",
"D20P01",
"D20P02",
"D24P01",
"D24P02")

# #emotions displayed during the collaborative problem-solving
# emotions <- c(
# "interested",
# "focused",
# "delighted",
# "satisfied",
# "confident",
# "amused",
# "relieved",
# "relaxed",
# "confused",
# "stressed",
# "dissatisfied",
# "annoyed",
# "frustrated",
# "grateful",
# "disappointed",
# "empathic",
# "bored",
# "surprised",
# "puzzled",
# "anxious",
# "impatient")

#All collaborative acts emitted by participants

# collaborative.processes <- c(
# "accept",
# "agree",
# "check.comprehension",
# "check.reception",
# "coordinate.teamwork",
# "disagree",
# "elicit.opinion",
# "elicit.partner.information",
# "elicit.proposition",
# "elicit.recall",
# "elicit.task.information",
# "give.explanation",
# "give.opinion.against",
# "give.opinion.for",
# "give.proposition",
# "give.recall",
# "give.self.information",
# "give.task.information",
# "incorporate",
# "manage.task",
# "other",
# "outside.activity",
# "relax.atmosphere",
# "show.active.listening",
# "show.reflection",
# "show.hostility",
# "show.solidarity",
# "tool.discourse",
# "use.social.convention")
#All collaborative acts emitted by participants representing at least 4 percents of the total

collaborative.processes <- c(
"accept",
"agree",
"give.opinion.for",
"give.proposition",
"give.self.information",
"give.task.information",
"manage.task",
"relax.atmosphere",
"show.reflection",
"tool.discourse")


#emotions displayed during the collaborative problem-solving representating at least 
emotions <- c(
"interested",
"focused",
"delighted",
"satisfied",
"amused",
"relaxed")

If there is not at least (max.window.size) collaborative processes following the emotion of interest -> this occurence is not taken into account for the computation of the relative use

If an emotion overlaps with one another (i.e., a new same emotion) is met before (max.window.size) is reached, this latest occurence is not taken into account for the compuation of the relative use

RTU computation

Interested

#Find cases available (participants that have shared the emotion)
interested.cases <- c()

emotion = "interested"
for (participant in participants_eat) {
    print(paste("Pour le participant ", participant," il y a", length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")]),"correspondance(s)"))
    interested.cases[participant] <- length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")])
}
[1] "Pour le participant  D02P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D02P02  il y a 3 correspondance(s)"
[1] "Pour le participant  D05P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D05P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D07P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D07P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D09P01  il y a 3 correspondance(s)"
[1] "Pour le participant  D09P02  il y a 4 correspondance(s)"
[1] "Pour le participant  D13P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D13P02  il y a 3 correspondance(s)"
[1] "Pour le participant  D16P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D16P02  il y a 3 correspondance(s)"
[1] "Pour le participant  D21P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D21P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D23P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D23P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D26P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D26P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D27P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D27P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D29P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D29P02  il y a 3 correspondance(s)"
interested.available.cases <- interested.cases[interested.cases != 0]
interested.available.cases
D02P01 D02P02 D05P02 D07P01 D07P02 D09P01 D09P02 D13P01 D13P02 D16P01 D16P02 D21P01 D21P02 D23P01 D23P02 D26P01 
     2      3      1      1      2      3      4      1      3      2      3      2      1      2      2      1 
D27P02 D29P01 D29P02 
     1      2      3 
length(interested.available.cases)
[1] 19
names(interested.available.cases)
 [1] "D02P01" "D02P02" "D05P02" "D07P01" "D07P02" "D09P01" "D09P02" "D13P01" "D13P02" "D16P01" "D16P02" "D21P01"
[13] "D21P02" "D23P01" "D23P02" "D26P01" "D27P02" "D29P01" "D29P02"
#interested sample
participants_eat_interested_P01 <- c("D02P01","D07P01","D09P01","D13P01","D16P01","D21P01","D23P01","D26P01","D29P01")
participants_eat_interested_P02 <- c("D02P02","D05P02","D07P02","D09P02","D13P02","D16P02","D21P02","D23P02","D27P02","D29P02")
#Compute the real-time use for the emotion interested

#select the subset of collaborative processes for a given participant. For the emotion interested, the (max.windows.size) collaborative processes of the other's partner from the same dyad are selected

#P02 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
interested.table.p2 <- data.frame(n)
rownames(interested.table.p2) <- collaborative.processes

for (p in participants_eat_interested_P01)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  interested.collaborative.processes.table <- data.frame(m)

  interested.times <- data[which(data$participant == p & data$shared.emotion =="interested"),c("unix.time.video")]
  interested.times.length <- length(interested.times)

  for (i in seq(1:length(interested.times)))
  {
    interested.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > interested.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  interested.collaborative.processes.table
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(interested.collaborative.processes.table)){
    if (anyNA(interested.collaborative.processes.table[,col])) {
      interested.times.length <- interested.times.length-1
      interested.collaborative.processes.table = interested.collaborative.processes.table[,!(names(interested.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(interested.collaborative.processes.table[interested.collaborative.processes.table == i])
  }
  x <- x/interested.times.length #number of emotion windows
  interested.table.p2[,paste0(substr(p, 1, 5),"2")] = x
}

interested.table.p2

#P01 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
interested.table.p1 <- data.frame(n)
rownames(interested.table.p1) <- collaborative.processes

for (p in participants_eat_interested_P02)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  interested.collaborative.processes.table <- data.frame(m)

  interested.times <- data[which(data$participant == p & data$shared.emotion == "interested"),c("unix.time.video")]
  interested.times.length <- length(interested.times)
  
  for (i in seq(1:length(interested.times)))
  {
    interested.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video >                                                 interested.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  interested.collaborative.processes.table
  
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(interested.collaborative.processes.table)){
    if (anyNA(interested.collaborative.processes.table[,col])) {
      interested.times.length <- interested.times.length-1
      interested.collaborative.processes.table = interested.collaborative.processes.table[,!(names(interested.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(interested.collaborative.processes.table[interested.collaborative.processes.table == i])
  }
  x <- x/interested.times.length #number of emotion windows
  interested.table.p1[,paste0(substr(p, 1, 5),"1")] = x
}

interested.table.p1    

interested.table <- cbind(interested.table.p1, interested.table.p2)
interested.table
#Compute the real-time when no emotion interested

#Select a subset of the data not including the emotion windows

#P02 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.interested.table.p2 <- data.frame(n)
rownames(non.interested.table.p2) <- collaborative.processes

for (p in participants_eat_interested_P01)
{
  interested.times <- data[which(data$participant == p & data$shared.emotion =="interested"),c("unix.time.video")]
  to.be.dropped <- vector()
  
  for (i in seq(1:length(interested.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > interested.times[i])[1:max.window.size])
  }
  
  #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)] 
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotion windows
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"2"),]
  
  #Keep a number of lines that is a multiple of max.windows.size = number of no-emotion windows
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  length(data.kept$participant)
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.interested.table.p2[,paste0(substr(p, 1, 5),"2")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.interested.table.p2

#P01 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.interested.table.p1 <- data.frame(n)
rownames(non.interested.table.p1) <- collaborative.processes

for (p in participants_eat_interested_P02)
{
  interested.times <- data[which(data$participant == p & data$shared.emotion =="interested"),c("unix.time.video")]
  
  to.be.dropped <- vector()
  
  for (i in seq(1:length(interested.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video > interested.times[i])[1:max.window.size])
    
  }
  
  #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)]
  
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotion windows
  
  print(data.kept)
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"1"),]
  
  #keep a number of lines that is a multiple of max.windows.size = number of no-emotion window
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.interested.table.p1[,paste0(substr(p, 1, 5),"1")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.interested.table.p1

non.interested.table <- cbind(non.interested.table.p1, non.interested.table.p2)
non.interested.table

for (col in colnames(non.interested.table)){
    print(sum(non.interested.table[,col])) 
}
[1] 3.671875
[1] 3.169492
[1] 3.375
[1] 3.157895
[1] 3.555556
[1] 3.214286
[1] 3.574468
[1] 3.789474
[1] 3.424242
[1] 3.470588
[1] 3.654545
[1] 3.581818
[1] 3.75
[1] 3.363636
[1] 3.416667
[1] 3.5
[1] 2.785714
[1] 3.342857
[1] 3.635135

Focused

#Find cases available for focused

focused.cases <- c()

emotion = "focused"
for (participant in participants_eat) {
    print(paste("Pour le participant ", participant," il y a", length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")]),"correspondance(s)"))
    focused.cases[participant] <- length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")])
}
[1] "Pour le participant  D02P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D02P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D05P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D05P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D07P01  il y a 4 correspondance(s)"
[1] "Pour le participant  D07P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D09P01  il y a 11 correspondance(s)"
[1] "Pour le participant  D09P02  il y a 4 correspondance(s)"
[1] "Pour le participant  D13P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D13P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D16P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D16P02  il y a 4 correspondance(s)"
[1] "Pour le participant  D21P01  il y a 3 correspondance(s)"
[1] "Pour le participant  D21P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D23P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D23P02  il y a 3 correspondance(s)"
[1] "Pour le participant  D26P01  il y a 4 correspondance(s)"
[1] "Pour le participant  D26P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D27P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D27P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D29P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D29P02  il y a 3 correspondance(s)"
focused.available.cases <- focused.cases[focused.cases != 0]
focused.available.cases
D02P01 D02P02 D05P01 D05P02 D07P01 D07P02 D09P01 D09P02 D13P01 D13P02 D16P01 D16P02 D21P01 D21P02 D23P01 D23P02 
     1      1      1      1      4      2     11      4      1      1      1      4      3      1      1      3 
D26P01 D26P02 D27P01 D27P02 D29P02 
     4      2      2      1      3 
length(focused.available.cases)
[1] 21
names(focused.available.cases)
 [1] "D02P01" "D02P02" "D05P01" "D05P02" "D07P01" "D07P02" "D09P01" "D09P02" "D13P01" "D13P02" "D16P01" "D16P02"
[13] "D21P01" "D21P02" "D23P01" "D23P02" "D26P01" "D26P02" "D27P01" "D27P02" "D29P02"
#focused sample
participants_eat_focused_P01 <- c("D02P01","D07P01","D07P01","D09P01","D13P01","D16P01","D21P01","D23P01","D26P01","D27P01")
participants_eat_focused_P02 <- c("D02P02","D05P02","D07P02","D09P02","D13P02","D16P02","D21P02","D23P02","D26P02","D27P02","D29P02")
#Compute the real-time use for the emotion focused

#select the subset of collaborative processes for a given participant. For the emotion focused, the (max.windows.size) collaborative processes of the other's partner from the same dyad are selected

#P02 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
focused.table.p2 <- data.frame(n)
rownames(focused.table.p2) <- collaborative.processes

for (p in participants_eat_focused_P01)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  focused.collaborative.processes.table <- data.frame(m)

  focused.times <- data[which(data$participant == p & data$shared.emotion =="focused"),c("unix.time.video")]
  focused.times.length <- length(focused.times)

  for (i in seq(1:length(focused.times)))
  {
    focused.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > focused.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  focused.collaborative.processes.table
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(focused.collaborative.processes.table)){
    if (anyNA(focused.collaborative.processes.table[,col])) {
      focused.times.length <- focused.times.length-1
      focused.collaborative.processes.table = focused.collaborative.processes.table[,!(names(focused.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(focused.collaborative.processes.table[focused.collaborative.processes.table == i])
  }
  x <- x/focused.times.length #number of emotion windows
  focused.table.p2[,paste0(substr(p, 1, 5),"2")] = x
}

focused.table.p2

#P01 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
focused.table.p1 <- data.frame(n)
rownames(focused.table.p1) <- collaborative.processes

for (p in participants_eat_focused_P02)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  focused.collaborative.processes.table <- data.frame(m)

  focused.times <- data[which(data$participant == p & data$shared.emotion == "focused"),c("unix.time.video")]
  focused.times.length <- length(focused.times)
  
  for (i in seq(1:length(focused.times)))
  {
    focused.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video >                                                 focused.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  focused.collaborative.processes.table
  
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(focused.collaborative.processes.table)){
    if (anyNA(focused.collaborative.processes.table[,col])) {
      focused.times.length <- focused.times.length-1
      focused.collaborative.processes.table = focused.collaborative.processes.table[,!(names(focused.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(focused.collaborative.processes.table[focused.collaborative.processes.table == i])
  }
  x <- x/focused.times.length #number of emotion windows
  focused.table.p1[,paste0(substr(p, 1, 5),"1")] = x
}

focused.table.p1    

focused.table <- cbind(focused.table.p1, focused.table.p2)
focused.table
#Compute the real-time use when no emotion focused

#Select a subset of the data not including the emotion windows

#P02 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.focused.table.p2 <- data.frame(n)
rownames(non.focused.table.p2) <- collaborative.processes

for (p in participants_eat_focused_P01)
{
  focused.times <- data[which(data$participant == p & data$shared.emotion =="focused"),c("unix.time.video")]
  
  to.be.dropped <- vector()
  
  for (i in seq(1:length(focused.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > focused.times[i])[1:max.window.size])
    
  }
  
  #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)] 
  
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotional chunks
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"2"),]
  
  #Keep a number of lines that is a multiple of max.windows.size = number of non-emotional chunks
  
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  length(data.kept$participant)
  
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.focused.table.p2[,paste0(substr(p, 1, 5),"2")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.focused.table.p2

#P01 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.focused.table.p1 <- data.frame(n)
rownames(non.focused.table.p1) <- collaborative.processes


for (p in participants_eat_focused_P02)
{
  focused.times <- data[which(data$participant == p & data$shared.emotion =="focused"),c("unix.time.video")]
  
  to.be.dropped <- vector()
  
  for (i in seq(1:length(focused.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video > focused.times[i])[1:max.window.size])
    
  }
  
  #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)] 
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotional chunks
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"1"),]
  
  #Keep a number of lines that is a multiple of max.windows.size = number of non-emotional chunks
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  length(data.kept$participant)
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.focused.table.p1[,paste0(substr(p, 1, 5),"1")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.focused.table.p1

non.focused.table <- cbind(non.focused.table.p1, non.focused.table.p2)
non.focused.table

Delighted

#Find cases available for delighted

delighted.cases <- c()

emotion = "delighted"
for (participant in participants_eat) {
    print(paste("Pour le participant ", participant," il y a", length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")]),"correspondance(s)"))
    delighted.cases[participant] <- length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")])
}
[1] "Pour le participant  D02P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D02P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D05P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D05P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D07P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D07P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D09P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D09P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D13P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D13P02  il y a 3 correspondance(s)"
[1] "Pour le participant  D16P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D16P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D21P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D21P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D23P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D23P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D26P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D26P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D27P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D27P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D29P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D29P02  il y a 1 correspondance(s)"
delighted.available.cases <- delighted.cases[delighted.cases != 0]
delighted.available.cases
D02P01 D05P01 D07P01 D07P02 D09P01 D09P02 D13P01 D13P02 D21P02 D26P01 D26P02 D27P01 D27P02 D29P01 D29P02 
     1      2      1      1      2      1      1      3      1      1      1      1      2      1      1 
length(delighted.available.cases)
[1] 15
names(delighted.available.cases)
 [1] "D02P01" "D05P01" "D07P01" "D07P02" "D09P01" "D09P02" "D13P01" "D13P02" "D21P02" "D26P01" "D26P02" "D27P01"
[13] "D27P02" "D29P01" "D29P02"
#delighted sample
participants_eat_delighted_P01 <- c("D02P01","D05P01","D09P01","D26P01","D27P01","D29P01")
participants_eat_delighted_P02 <- c("D09P02","D13P02","D21P02","D27P02","D29P02")
#Compute the real-time use for the emotion delighted

#select the subset of collaborative processes for a given participant. For the emotion delighted, the (max.windows.size) collaborative processes of the other's partner from the same dyad are selected

#P02 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
delighted.table.p2 <- data.frame(n)
rownames(delighted.table.p2) <- collaborative.processes

for (p in participants_eat_delighted_P01)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  delighted.collaborative.processes.table <- data.frame(m)

  delighted.times <- data[which(data$participant == p & data$shared.emotion =="delighted"),c("unix.time.video")]
  delighted.times.length <- length(delighted.times)

  for (i in seq(1:length(delighted.times)))
  {
    delighted.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > delighted.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  delighted.collaborative.processes.table
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(delighted.collaborative.processes.table)){
    if (anyNA(delighted.collaborative.processes.table[,col])) {
      delighted.times.length <- delighted.times.length-1
      delighted.collaborative.processes.table = delighted.collaborative.processes.table[,!(names(delighted.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(delighted.collaborative.processes.table[delighted.collaborative.processes.table == i])
  }
  x <- x/delighted.times.length #number of emotion windows
  delighted.table.p2[,paste0(substr(p, 1, 5),"2")] = x
}

delighted.table.p2

#P01 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
delighted.table.p1 <- data.frame(n)
rownames(delighted.table.p1) <- collaborative.processes

for (p in participants_eat_delighted_P02)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  delighted.collaborative.processes.table <- data.frame(m)

  delighted.times <- data[which(data$participant == p & data$shared.emotion == "delighted"),c("unix.time.video")]
  delighted.times.length <- length(delighted.times)
  
  for (i in seq(1:length(delighted.times)))
  {
    delighted.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video >                                                 delighted.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  delighted.collaborative.processes.table
  
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(delighted.collaborative.processes.table)){
    if (anyNA(delighted.collaborative.processes.table[,col])) {
      delighted.times.length <- delighted.times.length-1
      delighted.collaborative.processes.table = delighted.collaborative.processes.table[,!(names(delighted.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(delighted.collaborative.processes.table[delighted.collaborative.processes.table == i])
  }
  x <- x/delighted.times.length #number of emotion windows
  delighted.table.p1[,paste0(substr(p, 1, 5),"1")] = x
}

delighted.table.p1    

delighted.table <- cbind(delighted.table.p1, delighted.table.p2)
delighted.table
#Compute the real-time use when no emotion delighted

#Select a subset of the data not including the emotional collaborative processes that are emitted just after the emotion of interest

#P02 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.delighted.table.p2 <- data.frame(n)
rownames(non.delighted.table.p2) <- collaborative.processes

for (p in participants_eat_delighted_P01)
{
  delighted.times <- data[which(data$participant == p & data$shared.emotion =="delighted"),c("unix.time.video")]
  
  to.be.dropped <- vector()
  
  for (i in seq(1:length(delighted.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > delighted.times[i])[1:max.window.size])
    
  }
  
  #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)] 
  
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotional chunks
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"2"),]
  
  #keep a number of lines that is a multiple of max.windows.size = number of non-emotional chunks
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  length(data.kept$participant)
  
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.delighted.table.p2[,paste0(substr(p, 1, 5),"2")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.delighted.table.p2

#P01 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.delighted.table.p1 <- data.frame(n)
rownames(non.delighted.table.p1) <- collaborative.processes


for (p in participants_eat_delighted_P02)
{
  delighted.times <- data[which(data$participant == p & data$shared.emotion =="delighted"),c("unix.time.video")]
  
  to.be.dropped <- vector()
  
  for (i in seq(1:length(delighted.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video > delighted.times[i])[1:max.window.size])
    
  }
  
  #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)] 
  
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotional chunks
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"1"),]
  
  #keep a number of lines that is a multiple of max.windows.size = number of non-emotional chunks
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  length(data.kept$participant)
  
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.delighted.table.p1[,paste0(substr(p, 1, 5),"1")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.delighted.table.p1

non.delighted.table <- cbind(non.delighted.table.p1, non.delighted.table.p2)
non.delighted.table

Satisfied

#Find cases available for satisfied

satisfied.cases <- c()

emotion = "satisfied"
for (participant in participants_eat) {
    print(paste("Pour le participant ", participant," il y a", length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")]),"correspondance(s)"))
    satisfied.cases[participant] <- length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")])
}
[1] "Pour le participant  D02P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D02P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D05P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D05P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D07P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D07P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D09P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D09P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D13P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D13P02  il y a 4 correspondance(s)"
[1] "Pour le participant  D16P01  il y a 4 correspondance(s)"
[1] "Pour le participant  D16P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D21P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D21P02  il y a 3 correspondance(s)"
[1] "Pour le participant  D23P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D23P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D26P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D26P02  il y a 5 correspondance(s)"
[1] "Pour le participant  D27P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D27P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D29P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D29P02  il y a 2 correspondance(s)"
satisfied.available.cases <- satisfied.cases[satisfied.cases != 0]
satisfied.available.cases
D02P01 D02P02 D05P01 D09P01 D09P02 D13P01 D13P02 D16P01 D16P02 D21P01 D21P02 D23P01 D26P01 D26P02 D27P01 D27P02 
     2      2      2      2      2      1      4      4      1      2      3      2      2      5      1      2 
D29P01 D29P02 
     1      2 
length(satisfied.available.cases)
[1] 18
names(satisfied.available.cases)
 [1] "D02P01" "D02P02" "D05P01" "D09P01" "D09P02" "D13P01" "D13P02" "D16P01" "D16P02" "D21P01" "D21P02" "D23P01"
[13] "D26P01" "D26P02" "D27P01" "D27P02" "D29P01" "D29P02"
#satisfied sample
participants_eat_satisfied_P01 <- c("D02P01","D05P01","D09P01","D16P01","D21P01","D23P01","D26P01","D29P01")
participants_eat_satisfied_P02 <- c("D02P02","D09P02","D13P02","D16P02","D21P02","D26P02","D27P02","D29P02")
#Compute the real-time use for the emotion satisfied

#select the subset of collaborative processes for a given participant. For the emotion satisfied, the (max.windows.size) collaborative processes of the other's partner from the same dyad are selected

#P02 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
satisfied.table.p2 <- data.frame(n)
rownames(satisfied.table.p2) <- collaborative.processes

for (p in participants_eat_satisfied_P01)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  satisfied.collaborative.processes.table <- data.frame(m)

  satisfied.times <- data[which(data$participant == p & data$shared.emotion =="satisfied"),c("unix.time.video")]
  satisfied.times.length <- length(satisfied.times)

  for (i in seq(1:length(satisfied.times)))
  {
    satisfied.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > satisfied.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  satisfied.collaborative.processes.table
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(satisfied.collaborative.processes.table)){
    if (anyNA(satisfied.collaborative.processes.table[,col])) {
      satisfied.times.length <- satisfied.times.length-1
      satisfied.collaborative.processes.table = satisfied.collaborative.processes.table[,!(names(satisfied.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(satisfied.collaborative.processes.table[satisfied.collaborative.processes.table == i])
  }
  x <- x/satisfied.times.length #number of emotion windows
  satisfied.table.p2[,paste0(substr(p, 1, 5),"2")] = x
}

satisfied.table.p2

#P01 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
satisfied.table.p1 <- data.frame(n)
rownames(satisfied.table.p1) <- collaborative.processes

for (p in participants_eat_satisfied_P02)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  satisfied.collaborative.processes.table <- data.frame(m)

  satisfied.times <- data[which(data$participant == p & data$shared.emotion == "satisfied"),c("unix.time.video")]
  satisfied.times.length <- length(satisfied.times)
  
  for (i in seq(1:length(satisfied.times)))
  {
    satisfied.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video >                                                 satisfied.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  satisfied.collaborative.processes.table
  
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(satisfied.collaborative.processes.table)){
    if (anyNA(satisfied.collaborative.processes.table[,col])) {
      satisfied.times.length <- satisfied.times.length-1
      satisfied.collaborative.processes.table = satisfied.collaborative.processes.table[,!(names(satisfied.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(satisfied.collaborative.processes.table[satisfied.collaborative.processes.table == i])
  }
  x <- x/satisfied.times.length #number of emotion windows
  satisfied.table.p1[,paste0(substr(p, 1, 5),"1")] = x
}

satisfied.table.p1    

satisfied.table <- cbind(satisfied.table.p1, satisfied.table.p2)
satisfied.table
#Compute the relative use when no emotion satisfied

#Select a subset of the data not including the emotional collaborative processes that are emitted just after the emotion of interest

#results for P02 participants_eat

n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.satisfied.table.p2 <- data.frame(n)
rownames(non.satisfied.table.p2) <- collaborative.processes

for (p in participants_eat_satisfied_P01)
{
  satisfied.times <- data[which(data$participant == p & data$shared.emotion =="satisfied"),c("unix.time.video")]
  
  to.be.dropped <- vector()
  
  for (i in seq(1:length(satisfied.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > satisfied.times[i])[1:max.window.size])
    
  }
  
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)] #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotional chunks
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"2"),]
  
  #Keep a number of lines that is a multiple of max.windows.size = number of non-emotional chunks
  
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  length(data.kept$participant)
  
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.satisfied.table.p2[,paste0(substr(p, 1, 5),"2")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.satisfied.table.p2

#results for P01 participants_eat

n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.satisfied.table.p1 <- data.frame(n)
rownames(non.satisfied.table.p1) <- collaborative.processes


for (p in participants_eat_satisfied_P02)
{
  satisfied.times <- data[which(data$participant == p & data$shared.emotion =="satisfied"),c("unix.time.video")]
  
  to.be.dropped <- vector()
  
  for (i in seq(1:length(satisfied.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video > satisfied.times[i])[1:max.window.size])
    
  }
  
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)] #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotional chunks
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"1"),]
  
  #Keep a number of lines that is a multiple of max.windows.size = number of non-emotional chunks
  
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  length(data.kept$participant)
  
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.satisfied.table.p1[,paste0(substr(p, 1, 5),"1")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.satisfied.table.p1

non.satisfied.table <- cbind(non.satisfied.table.p1, non.satisfied.table.p2)
non.satisfied.table

Amused

#Find cases available for amused

amused.cases <- c()

emotion = "amused"
for (participant in participants_eat) {
    print(paste("Pour le participant ", participant," il y a", length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")]),"correspondance(s)"))
    amused.cases[participant] <- length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")])
}
[1] "Pour le participant  D02P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D02P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D05P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D05P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D07P01  il y a 3 correspondance(s)"
[1] "Pour le participant  D07P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D09P01  il y a 5 correspondance(s)"
[1] "Pour le participant  D09P02  il y a 3 correspondance(s)"
[1] "Pour le participant  D13P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D13P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D16P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D16P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D21P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D21P02  il y a 3 correspondance(s)"
[1] "Pour le participant  D23P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D23P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D26P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D26P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D27P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D27P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D29P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D29P02  il y a 0 correspondance(s)"
amused.available.cases <- amused.cases[amused.cases != 0]
amused.available.cases
D02P01 D05P01 D07P01 D07P02 D09P01 D09P02 D13P01 D13P02 D16P01 D21P01 D21P02 D23P01 D23P02 D26P01 D26P02 D27P01 
     1      1      3      1      5      3      2      1      1      2      3      1      1      2      2      2 
D27P02 D29P01 
     1      2 
length(amused.available.cases)
[1] 18
names(amused.available.cases)
 [1] "D02P01" "D05P01" "D07P01" "D07P02" "D09P01" "D09P02" "D13P01" "D13P02" "D16P01" "D21P01" "D21P02" "D23P01"
[13] "D23P02" "D26P01" "D26P02" "D27P01" "D27P02" "D29P01"
#amused sample
participants_eat_amused_P01 <- c("D02P01","D05P01","D07P01","D09P01","D13P01","D16P01","D21P01","D23P01","D26P01","D27P01","D29P01")
participants_eat_amused_P02 <- c("D07P02","D09P02","D13P02","D21P02","D23P02","D26P02","D27P02")
#Compute the real-time use for the emotion amused

#select the subset of collaborative processes for a given participant. For the emotion amused, the (max.windows.size) collaborative processes of the other's partner from the same dyad are selected

#P02 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
amused.table.p2 <- data.frame(n)
rownames(amused.table.p2) <- collaborative.processes

for (p in participants_eat_amused_P01)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  amused.collaborative.processes.table <- data.frame(m)

  amused.times <- data[which(data$participant == p & data$shared.emotion =="amused"),c("unix.time.video")]
  amused.times.length <- length(amused.times)

  for (i in seq(1:length(amused.times)))
  {
    amused.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > amused.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  amused.collaborative.processes.table
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(amused.collaborative.processes.table)){
    if (anyNA(amused.collaborative.processes.table[,col])) {
      amused.times.length <- amused.times.length-1
      amused.collaborative.processes.table = amused.collaborative.processes.table[,!(names(amused.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(amused.collaborative.processes.table[amused.collaborative.processes.table == i])
  }
  x <- x/amused.times.length #number of emotion windows
  amused.table.p2[,paste0(substr(p, 1, 5),"2")] = x
}

amused.table.p2

#P01 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
amused.table.p1 <- data.frame(n)
rownames(amused.table.p1) <- collaborative.processes

for (p in participants_eat_amused_P02)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  amused.collaborative.processes.table <- data.frame(m)

  amused.times <- data[which(data$participant == p & data$shared.emotion == "amused"),c("unix.time.video")]
  amused.times.length <- length(amused.times)
  
  for (i in seq(1:length(amused.times)))
  {
    amused.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video >                                                 amused.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  amused.collaborative.processes.table
  
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(amused.collaborative.processes.table)){
    if (anyNA(amused.collaborative.processes.table[,col])) {
      amused.times.length <- amused.times.length-1
      amused.collaborative.processes.table = amused.collaborative.processes.table[,!(names(amused.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(amused.collaborative.processes.table[amused.collaborative.processes.table == i])
  }
  x <- x/amused.times.length #number of emotion windows
  amused.table.p1[,paste0(substr(p, 1, 5),"1")] = x
}

amused.table.p1    

amused.table <- cbind(amused.table.p1, amused.table.p2)
amused.table
#Compute the relative use when no emotion amused

#Select a subset of the data not including the emotional collaborative processes that are emitted just after the emotion of interest

#results for P02 participants_eat

n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.amused.table.p2 <- data.frame(n)
rownames(non.amused.table.p2) <- collaborative.processes

for (p in participants_eat_amused_P01)
{
  amused.times <- data[which(data$participant == p & data$shared.emotion =="amused"),c("unix.time.video")]
  
  to.be.dropped <- vector()
  
  for (i in seq(1:length(amused.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > amused.times[i])[1:max.window.size])
    
  }
  
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)] #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotional chunks
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"2"),]
  
  #Keep a number of lines that is a multiple of max.windows.size = number of non-emotional chunks
  
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  length(data.kept$participant)
  
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.amused.table.p2[,paste0(substr(p, 1, 5),"2")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.amused.table.p2

#results for P01 participants_eat

n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.amused.table.p1 <- data.frame(n)
rownames(non.amused.table.p1) <- collaborative.processes


for (p in participants_eat_amused_P02)
{
  amused.times <- data[which(data$participant == p & data$shared.emotion =="amused"),c("unix.time.video")]
  
  to.be.dropped <- vector()
  
  for (i in seq(1:length(amused.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video > amused.times[i])[1:max.window.size])
    
  }
  
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)] #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotional chunks
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"1"),]
  
  #Keep a number of lines that is a multiple of max.windows.size = number of non-emotional chunks
  
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  length(data.kept$participant)
  
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.amused.table.p1[,paste0(substr(p, 1, 5),"1")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.amused.table.p1

non.amused.table <- cbind(non.amused.table.p1, non.amused.table.p2)
non.amused.table

Relaxed

#Find cases available for relaxed, i.e., the participants for which one or more sharing of relaxed occured

relaxed.cases <- c()

emotion = "relaxed"
for (participant in participants_eat) {
    print(paste("Pour le participant ", participant," il y a", length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")]),"correspondance(s)"))
    relaxed.cases[participant] <- length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")])
}
[1] "Pour le participant  D02P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D02P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D05P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D05P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D07P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D07P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D09P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D09P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D13P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D13P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D16P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D16P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D21P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D21P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D23P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D23P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D26P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D26P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D27P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D27P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D29P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D29P02  il y a 0 correspondance(s)"
relaxed.available.cases <- relaxed.cases[relaxed.cases != 0]
relaxed.available.cases
D05P01 D05P02 D07P01 D09P01 D09P02 D13P02 D16P02 D21P01 D21P02 D23P01 D26P01 D26P02 D27P01 D27P02 
     1      2      1      1      2      1      1      2      2      1      1      2      1      1 
length(relaxed.available.cases)
[1] 14
names(relaxed.available.cases)
 [1] "D05P01" "D05P02" "D07P01" "D09P01" "D09P02" "D13P02" "D16P02" "D21P01" "D21P02" "D23P01" "D26P01" "D26P02"
[13] "D27P01" "D27P02"
#relaxed sample
participants_eat_relaxed_P01 <- c("D05P01","D07P01","D09P01","D21P01","D23P01","D27P01")
participants_eat_relaxed_P02 <- c("D05P02","D09P02","D16P02","D21P02","D26P02","D27P02")
#Compute the real-time use for the emotion relaxed

#select the subset of collaborative processes for a given participant. For the emotion relaxed, the (max.windows.size) collaborative processes of the other's partner from the same dyad are selected

#P02 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
relaxed.table.p2 <- data.frame(n)
rownames(relaxed.table.p2) <- collaborative.processes

for (p in participants_eat_relaxed_P01)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  relaxed.collaborative.processes.table <- data.frame(m)

  relaxed.times <- data[which(data$participant == p & data$shared.emotion =="relaxed"),c("unix.time.video")]
  relaxed.times.length <- length(relaxed.times)

  for (i in seq(1:length(relaxed.times)))
  {
    relaxed.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > relaxed.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  relaxed.collaborative.processes.table
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(relaxed.collaborative.processes.table)){
    if (anyNA(relaxed.collaborative.processes.table[,col])) {
      relaxed.times.length <- relaxed.times.length-1
      relaxed.collaborative.processes.table = relaxed.collaborative.processes.table[,!(names(relaxed.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(relaxed.collaborative.processes.table[relaxed.collaborative.processes.table == i])
  }
  x <- x/relaxed.times.length #number of emotion windows
  relaxed.table.p2[,paste0(substr(p, 1, 5),"2")] = x
}

relaxed.table.p2

#P01 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
relaxed.table.p1 <- data.frame(n)
rownames(relaxed.table.p1) <- collaborative.processes

for (p in participants_eat_relaxed_P02)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  relaxed.collaborative.processes.table <- data.frame(m)

  relaxed.times <- data[which(data$participant == p & data$shared.emotion == "relaxed"),c("unix.time.video")]
  relaxed.times.length <- length(relaxed.times)
  
  for (i in seq(1:length(relaxed.times)))
  {
    relaxed.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video >                                                 relaxed.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  relaxed.collaborative.processes.table
  
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(relaxed.collaborative.processes.table)){
    if (anyNA(relaxed.collaborative.processes.table[,col])) {
      relaxed.times.length <- relaxed.times.length-1
      relaxed.collaborative.processes.table = relaxed.collaborative.processes.table[,!(names(relaxed.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(relaxed.collaborative.processes.table[relaxed.collaborative.processes.table == i])
  }
  x <- x/relaxed.times.length #number of emotion windows
  relaxed.table.p1[,paste0(substr(p, 1, 5),"1")] = x
}

relaxed.table.p1    

relaxed.table <- cbind(relaxed.table.p1, relaxed.table.p2)
relaxed.table
#Compute the relative use when no emotion relaxed

#Select a subset of the data not including the emotional collaborative processes that are emitted just after the emotion of interest

#results for P02 participants_eat

n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.relaxed.table.p2 <- data.frame(n)
rownames(non.relaxed.table.p2) <- collaborative.processes

for (p in participants_eat_relaxed_P01)
{
  relaxed.times <- data[which(data$participant == p & data$shared.emotion =="relaxed"),c("unix.time.video")]
  
  to.be.dropped <- vector()
  
  for (i in seq(1:length(relaxed.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > relaxed.times[i])[1:max.window.size])
    
  }
  
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)] #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotional chunks
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"2"),]
  
  #Keep a number of lines that is a multiple of max.windows.size = number of non-emotional chunks
  
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  length(data.kept$participant)
  
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.relaxed.table.p2[,paste0(substr(p, 1, 5),"2")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.relaxed.table.p2

#results for P01 participants_eat

n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.relaxed.table.p1 <- data.frame(n)
rownames(non.relaxed.table.p1) <- collaborative.processes


for (p in participants_eat_relaxed_P02)
{
  relaxed.times <- data[which(data$participant == p & data$shared.emotion =="relaxed"),c("unix.time.video")]
  
  to.be.dropped <- vector()
  
  for (i in seq(1:length(relaxed.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video > relaxed.times[i])[1:max.window.size])
    
  }
  
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)] #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotional chunks
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"1"),]
  
  #Keep a number of lines that is a multiple of max.windows.size = number of non-emotional chunks
  
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  length(data.kept$participant)
  
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.relaxed.table.p1[,paste0(substr(p, 1, 5),"1")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.relaxed.table.p1

non.relaxed.table <- cbind(non.relaxed.table.p1, non.relaxed.table.p2)
non.relaxed.table

Confident

#Find cases available for confident, i.e., the participants for which one or more sharing of confident occured

confident.cases <- c()

emotion = "confident"
for (participant in participants_eat) {
    print(paste("Pour le participant ", participant," il y a", length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")]),"correspondance(s)"))
    confident.cases[participant] <- length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")])
}
[1] "Pour le participant  D02P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D02P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D05P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D05P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D07P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D07P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D09P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D09P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D13P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D13P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D16P01  il y a 4 correspondance(s)"
[1] "Pour le participant  D16P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D21P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D21P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D23P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D23P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D26P01  il y a 3 correspondance(s)"
[1] "Pour le participant  D26P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D27P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D27P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D29P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D29P02  il y a 0 correspondance(s)"
confident.available.cases <- confident.cases[confident.cases != 0]
confident.available.cases
D02P02 D05P02 D09P01 D16P01 D16P02 D26P01 D26P02 D27P01 D29P01 
     2      1      1      4      1      3      2      1      1 
length(confident.available.cases)
[1] 9
names(confident.available.cases)
[1] "D02P02" "D05P02" "D09P01" "D16P01" "D16P02" "D26P01" "D26P02" "D27P01" "D29P01"
#confident sample
participants_eat_confident_P01 <- c("D09P01","D16P01","D26P01","D27P01","D29P01")
participants_eat_confident_P02 <- c("D02P02","D05P02","D16P02","D26P02")
#Compute the real-time use for the emotion confident

#select the subset of collaborative processes for a given participant. For the emotion confident, the (max.windows.size) collaborative processes of the other's partner from the same dyad are selected

#P02 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
confident.table.p2 <- data.frame(n)
rownames(confident.table.p2) <- collaborative.processes

for (p in participants_eat_confident_P01)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  confident.collaborative.processes.table <- data.frame(m)

  confident.times <- data[which(data$participant == p & data$shared.emotion =="confident"),c("unix.time.video")]
  confident.times.length <- length(confident.times)

  for (i in seq(1:length(confident.times)))
  {
    confident.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > confident.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  confident.collaborative.processes.table
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(confident.collaborative.processes.table)){
    if (anyNA(confident.collaborative.processes.table[,col])) {
      confident.times.length <- confident.times.length-1
      confident.collaborative.processes.table = confident.collaborative.processes.table[,!(names(confident.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(confident.collaborative.processes.table[confident.collaborative.processes.table == i])
  }
  x <- x/confident.times.length #number of emotion windows
  confident.table.p2[,paste0(substr(p, 1, 5),"2")] = x
}

confident.table.p2

#P01 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
confident.table.p1 <- data.frame(n)
rownames(confident.table.p1) <- collaborative.processes

for (p in participants_eat_confident_P02)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  confident.collaborative.processes.table <- data.frame(m)

  confident.times <- data[which(data$participant == p & data$shared.emotion == "confident"),c("unix.time.video")]
  confident.times.length <- length(confident.times)
  
  for (i in seq(1:length(confident.times)))
  {
    confident.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video >                                                 confident.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  confident.collaborative.processes.table
  
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(confident.collaborative.processes.table)){
    if (anyNA(confident.collaborative.processes.table[,col])) {
      confident.times.length <- confident.times.length-1
      confident.collaborative.processes.table = confident.collaborative.processes.table[,!(names(confident.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(confident.collaborative.processes.table[confident.collaborative.processes.table == i])
  }
  x <- x/confident.times.length #number of emotion windows
  confident.table.p1[,paste0(substr(p, 1, 5),"1")] = x
}

confident.table.p1    

confident.table <- cbind(confident.table.p1, confident.table.p2)
confident.table
#Compute the relative use when no emotion confident

#Select a subset of the data not including the emotional collaborative processes that are emitted just after the emotion of interest

#results for P02 participants_eat

n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.confident.table.p2 <- data.frame(n)
rownames(non.confident.table.p2) <- collaborative.processes

for (p in participants_eat_confident_P01)
{
  confident.times <- data[which(data$participant == p & data$shared.emotion =="confident"),c("unix.time.video")]
  
  to.be.dropped <- vector()
  
  for (i in seq(1:length(confident.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > confident.times[i])[1:max.window.size])
    
  }
  
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)] #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotional chunks
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"2"),]
  
  #Keep a number of lines that is a multiple of max.windows.size = number of non-emotional chunks
  
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  length(data.kept$participant)
  
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.confident.table.p2[,paste0(substr(p, 1, 5),"2")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.confident.table.p2

#results for P01 participants_eat

n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.confident.table.p1 <- data.frame(n)
rownames(non.confident.table.p1) <- collaborative.processes


for (p in participants_eat_confident_P02)
{
  confident.times <- data[which(data$participant == p & data$shared.emotion =="confident"),c("unix.time.video")]
  
  to.be.dropped <- vector()
  
  for (i in seq(1:length(confident.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video > confident.times[i])[1:max.window.size])
    
  }
  
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)] #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotional chunks
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"1"),]
  
  #Keep a number of lines that is a multiple of max.windows.size = number of non-emotion chunks
  
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  length(data.kept$participant)
  
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.confident.table.p1[,paste0(substr(p, 1, 5),"1")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.confident.table.p1

non.confident.table <- cbind(non.confident.table.p1, non.confident.table.p2)
non.confident.table

Confused

#Find cases available for confused, i.e., the participants for which one or more sharing of confused occured

confused.cases <- c()

emotion = "confused"
for (participant in participants_eat) {
    print(paste("Pour le participant ", participant," il y a", length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")]),"correspondance(s)"))
    confused.cases[participant] <- length(data[which(data$participant == participant & data$shared.emotion == emotion),c("shared.emotion")])
}
[1] "Pour le participant  D02P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D02P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D05P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D05P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D07P01  il y a 1 correspondance(s)"
[1] "Pour le participant  D07P02  il y a 1 correspondance(s)"
[1] "Pour le participant  D09P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D09P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D13P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D13P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D16P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D16P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D21P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D21P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D23P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D23P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D26P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D26P02  il y a 2 correspondance(s)"
[1] "Pour le participant  D27P01  il y a 0 correspondance(s)"
[1] "Pour le participant  D27P02  il y a 0 correspondance(s)"
[1] "Pour le participant  D29P01  il y a 2 correspondance(s)"
[1] "Pour le participant  D29P02  il y a 0 correspondance(s)"
confused.available.cases <- confused.cases[confused.cases != 0]
confused.available.cases
D05P01 D07P01 D07P02 D13P01 D26P02 D29P01 
     1      1      1      2      2      2 
length(confused.available.cases)
[1] 6
names(confused.available.cases)
[1] "D05P01" "D07P01" "D07P02" "D13P01" "D26P02" "D29P01"
#confused sample
participants_eat_confused_P01 <- c("D05P01","D07P01","D13P01","D29P01")
participants_eat_confused_P02 <- c("D07P02","D26P02")
#Compute the real-time use for the emotion confused

#select the subset of collaborative processes for a given participant. For the emotion confused, the (max.windows.size) collaborative processes of the other's partner from the same dyad are selected

#P02 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
confused.table.p2 <- data.frame(n)
rownames(confused.table.p2) <- collaborative.processes

for (p in participants_eat_confused_P01)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  confused.collaborative.processes.table <- data.frame(m)

  confused.times <- data[which(data$participant == p & data$shared.emotion =="confused"),c("unix.time.video")]
  confused.times.length <- length(confused.times)

  for (i in seq(1:length(confused.times)))
  {
    confused.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > confused.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  confused.collaborative.processes.table
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(confused.collaborative.processes.table)){
    if (anyNA(confused.collaborative.processes.table[,col])) {
      confused.times.length <- confused.times.length-1
      confused.collaborative.processes.table = confused.collaborative.processes.table[,!(names(confused.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(confused.collaborative.processes.table[confused.collaborative.processes.table == i])
  }
  x <- x/confused.times.length #number of emotion windows
  confused.table.p2[,paste0(substr(p, 1, 5),"2")] = x
}

confused.table.p2

#P01 participants
n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
confused.table.p1 <- data.frame(n)
rownames(confused.table.p1) <- collaborative.processes

for (p in participants_eat_confused_P02)
{
  m <- matrix(data=NA,nrow=max.window.size,ncol=0)
  confused.collaborative.processes.table <- data.frame(m)

  confused.times <- data[which(data$participant == p & data$shared.emotion == "confused"),c("unix.time.video")]
  confused.times.length <- length(confused.times)
  
  for (i in seq(1:length(confused.times)))
  {
    confused.collaborative.processes.table[,paste0("occurence",i)] <- data[which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video >                                                 confused.times[i]),c("collaborative.processes")][1:max.window.size] 
  }

  confused.collaborative.processes.table
  
  #check if the emotion windows all have a length of max.window.size
  #when it is not the case, the emotion window is removed
  for (col in colnames(confused.collaborative.processes.table)){
    if (anyNA(confused.collaborative.processes.table[,col])) {
      confused.times.length <- confused.times.length-1
      confused.collaborative.processes.table = confused.collaborative.processes.table[,!(names(confused.collaborative.processes.table) %in% c(col))]
    }
  }
  
  #compute the real-time use for every collaborative process
  x <- c()
  for (i in collaborative.processes)
  {
    x[i] <- length(confused.collaborative.processes.table[confused.collaborative.processes.table == i])
  }
  x <- x/confused.times.length #number of emotion windows
  confused.table.p1[,paste0(substr(p, 1, 5),"1")] = x
}

confused.table.p1    

confused.table <- cbind(confused.table.p1, confused.table.p2)
confused.table
#Compute the relative use when no emotion confused

#Select a subset of the data not including the emotional collaborative processes that are emitted just after the emotion of interest

#results for P02 participants_eat

n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.confused.table.p2 <- data.frame(n)
rownames(non.confused.table.p2) <- collaborative.processes

for (p in participants_eat_confused_P01)
{
  confused.times <- data[which(data$participant == p & data$shared.emotion =="confused"),c("unix.time.video")]
  
  to.be.dropped <- vector()
  
  for (i in seq(1:length(confused.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"2") & data$unix.time.video > confused.times[i])[1:max.window.size])
    
  }
  
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)] #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotional chunks
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"2"),]
  
  #Keep a number of lines that is a multiple of max.windows.size = number of non-emotional chunks
  
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  length(data.kept$participant)
  
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.confused.table.p2[,paste0(substr(p, 1, 5),"2")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.confused.table.p2

#results for P01 participants_eat

n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
non.confused.table.p1 <- data.frame(n)
rownames(non.confused.table.p1) <- collaborative.processes


for (p in participants_eat_confused_P02)
{
  confused.times <- data[which(data$participant == p & data$shared.emotion =="confused"),c("unix.time.video")]
  
  to.be.dropped <- vector()
  
  for (i in seq(1:length(confused.times)))
  {
    to.be.dropped <- c(to.be.dropped, which(data$participant == paste0(substr(p, 1, 5),"1") & data$unix.time.video > confused.times[i])[1:max.window.size])
    
  }
  
  to.be.dropped <- to.be.dropped[!is.na(to.be.dropped)] #remove NA when max.window.size goes out of bounds because the end of collaborative acts for that participant is reached
  
  data.kept <- data[-to.be.dropped,] #data.kept is the data without emotional chunks
  
  data.kept <- data.kept[data.kept$participant == paste0(substr(p, 1, 5),"1"),]
  
  #Keep a number of lines that is a multiple of max.windows.size = number of non-emotion chunks
  
  n <- nrow(data.kept)
  data.kept <- data.kept[c(1:(n-(n%%max.window.size))),]
  
  length(data.kept$participant)
  
  
  results <- c()
  for (process in collaborative.processes)
    {
    results <- c(results, sum(data.kept$collaborative.processes==process))
    }
  
  non.confused.table.p1[,paste0(substr(p, 1, 5),"1")] <- results/(length(data.kept$collaborative.processes)%/%max.window.size)
  results <- c()
  
}

non.confused.table.p1

non.confused.table <- cbind(non.confused.table.p1, non.confused.table.p2)
non.confused.table

Randomization tests

number_of_permutations = 9999

n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
emotions.results.permutation.correction <- data.frame(n)
rownames(emotions.results.permutation.correction) <- collaborative.processes

Interested

emotions.results.permutation.correction$interested_p.value <- p.adjust(results, method="BH")
emotions.results.permutation.correction$interested_mean.no.emotion <- mean.no.emotion
emotions.results.permutation.correction$interested_mean.emotion <- mean.emotion
emotions.results.permutation.correction$interested_sd.no.emotion <- sd.no.emotion
emotions.results.permutation.correction$interested_sd.emotion <- sd.emotion

emotions.results.permutation.correction[,c("interested_p.value"), drop=FALSE]

Focused

results <- c()
mean.no.emotion <- c()
mean.emotion <- c()
sd.no.emotion <- c()
sd.emotion <- c()

for (process in collaborative.processes) {

  observed.mean.difference <- mean(as.numeric(focused.table[process,])) - mean(as.numeric(non.focused.table[process,]))
  observed.mean.difference
  
  random.mean.differences <- c(observed.mean.difference)
  
  whole.sample <- c(as.numeric(focused.table[process,]),as.numeric(non.focused.table[process,])) #put together the two samples
  
  for (i in 1:number_of_permutations) {
    
    random.sample <- sample(whole.sample) #randomize the sample
    
    random.treatment.sample <- random.sample[1:length(as.numeric(focused.table[process,]))] #select new treatment sample
    random.control.sample <- random.sample[(1+length(as.numeric(focused.table[process,]))):length(random.sample)] #select new control sample
    random.mean.differences <- c(random.mean.differences,mean(random.treatment.sample)-mean(random.control.sample))
  
  }
  
    results <- c(results, sum(abs(random.mean.differences) >= abs(observed.mean.difference)) / length(random.mean.differences))
    mean.no.emotion <- c(mean.no.emotion,mean(as.numeric(non.focused.table[process,])))
    mean.emotion <- c(mean.emotion,mean(as.numeric(focused.table[process,])))
    sd.no.emotion <- c(sd.no.emotion,sd(as.numeric(non.focused.table[process,])))
    sd.emotion <- c(sd.emotion,sd(as.numeric(focused.table[process,])))
    
    #graphs
    hist(random.mean.differences, main = paste0("Sampling distribution ",process), xlab = "Mean difference", prob = F, col = "darkred")
    abline(v = observed.mean.difference, col = "blue", lwd = 2)
    
}

emotions.results.permutation.correction$focused_p.value <- p.adjust(results, method="BH")
emotions.results.permutation.correction$focused_mean.no.emotion <- mean.no.emotion
emotions.results.permutation.correction$focused_mean.emotion <- mean.emotion
emotions.results.permutation.correction$focused_sd.no.emotion <- sd.no.emotion
emotions.results.permutation.correction$focused_sd.emotion <- sd.emotion

emotions.results.permutation.correction[,c("focused_p.value"), drop=FALSE]

Delighted

results <- c()
mean.no.emotion <- c()
mean.emotion <- c()
sd.no.emotion <- c()
sd.emotion <- c()

for (process in collaborative.processes) {

  observed.mean.difference <- mean(as.numeric(delighted.table[process,])) - mean(as.numeric(non.delighted.table[process,]))
  observed.mean.difference
  
  random.mean.differences <- c(observed.mean.difference)
  
  whole.sample <- c(as.numeric(delighted.table[process,]),as.numeric(non.delighted.table[process,])) #put together the two samples
  
  for (i in 1:number_of_permutations) {
    
    random.sample <- sample(whole.sample) #randomize the sample
    random.treatment.sample <- random.sample[1:length(as.numeric(delighted.table[process,]))] #select new treatment sample
    random.control.sample <- random.sample[(1+length(as.numeric(delighted.table[process,]))):length(random.sample)] #select new control sample
    random.mean.differences <- c(random.mean.differences,mean(random.treatment.sample)-mean(random.control.sample))
  
  }
  
    results <- c(results, sum(abs(random.mean.differences) >= abs(observed.mean.difference)) / length(random.mean.differences))
    mean.no.emotion <- c(mean.no.emotion,mean(as.numeric(non.delighted.table[process,])))
    mean.emotion <- c(mean.emotion,mean(as.numeric(delighted.table[process,])))
    sd.no.emotion <- c(sd.no.emotion,sd(as.numeric(non.delighted.table[process,])))
    sd.emotion <- c(sd.emotion,sd(as.numeric(delighted.table[process,])))
    
    #graphs
    hist(random.mean.differences, main = paste0("Sampling distribution ",process), xlab = "Mean difference", prob = F, col = "darkred")
    abline(v = observed.mean.difference, col = "blue", lwd = 2)
    
}

emotions.results.permutation.correction$delighted_p.value <- p.adjust(results, method="BH")
emotions.results.permutation.correction$delighted_mean.no.emotion <- mean.no.emotion
emotions.results.permutation.correction$delighted_mean.emotion <- mean.emotion
emotions.results.permutation.correction$delighted_sd.no.emotion <- sd.no.emotion
emotions.results.permutation.correction$delighted_sd.emotion <- sd.emotion

emotions.results.permutation.correction[,c("delighted_p.value"), drop=FALSE]

Satisfied

results <- c()
mean.no.emotion <- c()
mean.emotion <- c()
sd.no.emotion <- c()
sd.emotion <- c()

for (process in collaborative.processes) {

  observed.mean.difference <- mean(as.numeric(satisfied.table[process,])) - mean(as.numeric(non.satisfied.table[process,]))
  observed.mean.difference
  
  random.mean.differences <- c(observed.mean.difference)
  
  whole.sample <- c(as.numeric(satisfied.table[process,]),as.numeric(non.satisfied.table[process,])) #put together the two samples
  
  for (i in 1:number_of_permutations) {
    
    random.sample <- sample(whole.sample) #randomize the sample
    random.treatment.sample <- random.sample[1:length(as.numeric(satisfied.table[process,]))] #select new treatment sample
    random.control.sample <- random.sample[(1+length(as.numeric(satisfied.table[process,]))):length(random.sample)] #select new control sample
    random.mean.differences <- c(random.mean.differences,mean(random.treatment.sample)-mean(random.control.sample))
  
  }
  
    results <- c(results, sum(abs(random.mean.differences) >= abs(observed.mean.difference)) / length(random.mean.differences))
    mean.no.emotion <- c(mean.no.emotion,mean(as.numeric(non.satisfied.table[process,])))
    mean.emotion <- c(mean.emotion,mean(as.numeric(satisfied.table[process,])))
    sd.no.emotion <- c(sd.no.emotion,sd(as.numeric(non.satisfied.table[process,])))
    sd.emotion <- c(sd.emotion,sd(as.numeric(satisfied.table[process,])))
    
    #graphs
    hist(random.mean.differences, main = paste0("Sampling distribution ",process), xlab = "Mean difference", prob = F, col = "darkred")
    abline(v = observed.mean.difference, col = "blue", lwd = 2)
    
}

emotions.results.permutation.correction$satisfied_p.value <- p.adjust(results, method="BH")
emotions.results.permutation.correction$satisfied_mean.no.emotion <- mean.no.emotion
emotions.results.permutation.correction$satisfied_mean.emotion <- mean.emotion
emotions.results.permutation.correction$satisfied_sd.no.emotion <- sd.no.emotion
emotions.results.permutation.correction$satisfied_sd.emotion <- sd.emotion

emotions.results.permutation.correction[,c("satisfied_p.value"), drop=FALSE]

Amused

results <- c()
mean.no.emotion <- c()
mean.emotion <- c()
sd.no.emotion <- c()
sd.emotion <- c()

for (process in collaborative.processes) {

  observed.mean.difference <- mean(as.numeric(amused.table[process,])) - mean(as.numeric(non.amused.table[process,]))
  observed.mean.difference
  
  random.mean.differences <- c(observed.mean.difference)
  
  whole.sample <- c(as.numeric(amused.table[process,]),as.numeric(non.amused.table[process,])) #put together the two samples
  
  for (i in 1:number_of_permutations) {
    
    random.sample <- sample(whole.sample) #randomize the sample
    random.treatment.sample <- random.sample[1:length(as.numeric(amused.table[process,]))] #select new treatment sample
    random.control.sample <- random.sample[(1+length(as.numeric(amused.table[process,]))):length(random.sample)] #select new control sample
    random.mean.differences <- c(random.mean.differences,mean(random.treatment.sample)-mean(random.control.sample))
  
  }
  
    results <- c(results, sum(abs(random.mean.differences) >= abs(observed.mean.difference)) / length(random.mean.differences))
    mean.no.emotion <- c(mean.no.emotion,mean(as.numeric(non.amused.table[process,])))
    mean.emotion <- c(mean.emotion,mean(as.numeric(amused.table[process,])))
    sd.no.emotion <- c(sd.no.emotion,sd(as.numeric(non.amused.table[process,])))
    sd.emotion <- c(sd.emotion,sd(as.numeric(amused.table[process,])))
    
    #graphs
    hist(random.mean.differences, main = paste0("Sampling distribution ",process), xlab = "Mean difference", prob = F, col = "darkred")
    abline(v = observed.mean.difference, col = "blue", lwd = 2)
    
}

emotions.results.permutation.correction$amused_p.value <- p.adjust(results, method="BH")
emotions.results.permutation.correction$amused_mean.no.emotion <- mean.no.emotion
emotions.results.permutation.correction$amused_mean.emotion <- mean.emotion
emotions.results.permutation.correction$amused_sd.no.emotion <- sd.no.emotion
emotions.results.permutation.correction$amused_sd.emotion <- sd.emotion

emotions.results.permutation.correction[,c("amused_p.value"), drop=FALSE]

Relaxed

results <- c()
mean.no.emotion <- c()
mean.emotion <- c()
sd.no.emotion <- c()
sd.emotion <- c()

for (process in collaborative.processes) {

  observed.mean.difference <- mean(as.numeric(relaxed.table[process,])) - mean(as.numeric(non.relaxed.table[process,]))
  observed.mean.difference
  
  random.mean.differences <- c(observed.mean.difference)
  
  whole.sample <- c(as.numeric(relaxed.table[process,]),as.numeric(non.relaxed.table[process,])) #put together the two samples
  
  for (i in 1:number_of_permutations) {
    
    random.sample <- sample(whole.sample) #randomize the sample
    random.treatment.sample <- random.sample[1:length(as.numeric(relaxed.table[process,]))] #select new treatment sample
    random.control.sample <- random.sample[(1+length(as.numeric(relaxed.table[process,]))):length(random.sample)] #select new control sample
    random.mean.differences <- c(random.mean.differences,mean(random.treatment.sample)-mean(random.control.sample))
  
  }
  
    results <- c(results, sum(abs(random.mean.differences) >= abs(observed.mean.difference)) / length(random.mean.differences))
    mean.no.emotion <- c(mean.no.emotion,mean(as.numeric(non.relaxed.table[process,])))
    mean.emotion <- c(mean.emotion,mean(as.numeric(relaxed.table[process,])))
    sd.no.emotion <- c(sd.no.emotion,sd(as.numeric(non.relaxed.table[process,])))
    sd.emotion <- c(sd.emotion,sd(as.numeric(relaxed.table[process,])))
    
    #graphs
    hist(random.mean.differences, main = paste0("Sampling distribution ",process), xlab = "Mean difference", prob = F, col = "darkred")
    abline(v = observed.mean.difference, col = "blue", lwd = 2)
    
}

emotions.results.permutation.correction$relaxed_p.value <- p.adjust(results, method="BH")
emotions.results.permutation.correction$relaxed_mean.no.emotion <- mean.no.emotion
emotions.results.permutation.correction$relaxed_mean.emotion <- mean.emotion
emotions.results.permutation.correction$relaxed_sd.no.emotion <- sd.no.emotion
emotions.results.permutation.correction$relaxed_sd.emotion <- sd.emotion

emotions.results.permutation.correction$mean.diff.relaxed <- (mean.emotion-mean.no.emotion)
emotions.results.permutation.correction$mean.diff.relaxed
 [1] -0.49692109 -0.35209996 -0.53122708  0.33380400 -0.20373705  0.15276475  0.21975936 -0.08681058  0.43739989
[10] -0.04730812
emotions.results.permutation.correction[,c("relaxed_p.value","mean.diff.relaxed")]

Wilcoxon tests with Benjamini-Hochberg correction

n <- matrix(data=NA,nrow=length(collaborative.processes),ncol=0)
emotions.results.bh.correction <- data.frame(n)
rownames(emotions.results.bh.correction) <- collaborative.processes

Interested

results <- c()
mean.no.emotion <- c()
mean.emotion <- c()
sd.no.emotion <- c()
sd.emotion <- c()
 for (process in collaborative.processes)
   {
   
   results <- c(results, wilcox.test(t(interested.table[process,]),t(non.interested.table[process,]))$p.value)
   mean.no.emotion <- c(mean.no.emotion,mean(as.numeric(non.interested.table[process,])))
   mean.emotion <- c(mean.emotion,mean(as.numeric(interested.table[process,])))
   sd.no.emotion <- c(sd.no.emotion,sd(as.numeric(non.interested.table[process,])))
   sd.emotion <- c(sd.emotion,sd(as.numeric(interested.table[process,])))
  }
impossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequos
emotions.results.bh.correction$interested_p.value <- p.adjust(results, method="BH")
emotions.results.bh.correction$interested_mean.no.emotion <- mean.no.emotion
emotions.results.bh.correction$interested_mean.emotion <- mean.emotion
emotions.results.bh.correction$interested_sd.no.emotion <- sd.no.emotion
emotions.results.bh.correction$interested_sd.emotion <- sd.emotion

focused

results <- c()
mean.no.emotion <- c()
mean.emotion <- c()
sd.no.emotion <- c()
sd.emotion <- c()
 for (process in collaborative.processes)
   {
   
   results <- c(results, wilcox.test(t(focused.table[process,]),t(non.focused.table[process,]))$p.value)
   mean.no.emotion <- c(mean.no.emotion,mean(as.numeric(non.focused.table[process,])))
   mean.emotion <- c(mean.emotion,mean(as.numeric(focused.table[process,])))
   sd.no.emotion <- c(sd.no.emotion,sd(as.numeric(non.focused.table[process,])))
   sd.emotion <- c(sd.emotion,sd(as.numeric(focused.table[process,])))
  }
impossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequos
emotions.results.bh.correction$focused_p.value <- p.adjust(results, method="BH")
emotions.results.bh.correction$focused_mean.no.emotion <- mean.no.emotion
emotions.results.bh.correction$focused_mean.emotion <- mean.emotion
emotions.results.bh.correction$focused_sd.no.emotion <- sd.no.emotion
emotions.results.bh.correction$focused_sd.emotion <- sd.emotion

delighted

results <- c()
mean.no.emotion <- c()
mean.emotion <- c()
sd.no.emotion <- c()
sd.emotion <- c()
 for (process in collaborative.processes)
   {
   
   results <- c(results, wilcox.test(t(delighted.table[process,]),t(non.delighted.table[process,]))$p.value)
   mean.no.emotion <- c(mean.no.emotion,mean(as.numeric(non.delighted.table[process,])))
   mean.emotion <- c(mean.emotion,mean(as.numeric(delighted.table[process,])))
   sd.no.emotion <- c(sd.no.emotion,sd(as.numeric(non.delighted.table[process,])))
   sd.emotion <- c(sd.emotion,sd(as.numeric(delighted.table[process,])))
   
   
  }
impossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequos
emotions.results.bh.correction$delighted_p.value <- p.adjust(results, method="BH")
emotions.results.bh.correction$delighted_mean.no.emotion <- mean.no.emotion
emotions.results.bh.correction$delighted_mean.emotion <- mean.emotion
emotions.results.bh.correction$delighted_sd.no.emotion <- sd.no.emotion
emotions.results.bh.correction$delighted_sd.emotion <- sd.emotion

satisfied

results <- c()
mean.no.emotion <- c()
mean.emotion <- c()
sd.no.emotion <- c()
sd.emotion <- c()
 for (process in collaborative.processes)
   {
   
   results <- c(results, wilcox.test(t(satisfied.table[process,]),t(non.satisfied.table[process,]))$p.value)
   mean.no.emotion <- c(mean.no.emotion,mean(as.numeric(non.satisfied.table[process,])))
   mean.emotion <- c(mean.emotion,mean(as.numeric(satisfied.table[process,])))
   sd.no.emotion <- c(sd.no.emotion,sd(as.numeric(non.satisfied.table[process,])))
   sd.emotion <- c(sd.emotion,sd(as.numeric(satisfied.table[process,])))
   
  }
impossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequos
emotions.results.bh.correction$satisfied_p.value <- p.adjust(results, method="BH")
emotions.results.bh.correction$satisfied_mean.no.emotion <- mean.no.emotion
emotions.results.bh.correction$satisfied_mean.emotion <- mean.emotion
emotions.results.bh.correction$satisfied_sd.no.emotion <- sd.no.emotion
emotions.results.bh.correction$satisfied_sd.emotion <- sd.emotion

amused

results <- c()
mean.no.emotion <- c()
mean.emotion <- c()
sd.no.emotion <- c()
sd.emotion <- c()
 for (process in collaborative.processes)
   {
   
   results <- c(results, wilcox.test(t(amused.table[process,]),t(non.amused.table[process,]))$p.value)
   mean.no.emotion <- c(mean.no.emotion,mean(as.numeric(non.amused.table[process,])))
   mean.emotion <- c(mean.emotion,mean(as.numeric(amused.table[process,])))
   sd.no.emotion <- c(sd.no.emotion,sd(as.numeric(non.amused.table[process,])))
   sd.emotion <- c(sd.emotion,sd(as.numeric(amused.table[process,])))
   
  }
impossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequos
emotions.results.bh.correction$amused_p.value <- p.adjust(results, method="BH")
emotions.results.bh.correction$amused_mean.no.emotion <- mean.no.emotion
emotions.results.bh.correction$amused_mean.emotion <- mean.emotion
emotions.results.bh.correction$amused_sd.no.emotion <- sd.no.emotion
emotions.results.bh.correction$amused_sd.emotion <- sd.emotion

relaxed

results <- c()
mean.no.emotion <- c()
mean.emotion <- c()
sd.no.emotion <- c()
sd.emotion <- c()
 for (process in collaborative.processes)
   {
   
   results <- c(results, wilcox.test(t(relaxed.table[process,]),t(non.relaxed.table[process,]))$p.value)
   mean.no.emotion <- c(mean.no.emotion,mean(as.numeric(non.relaxed.table[process,])))
   mean.emotion <- c(mean.emotion,mean(as.numeric(relaxed.table[process,])))
   sd.no.emotion <- c(sd.no.emotion,sd(as.numeric(non.relaxed.table[process,])))
   sd.emotion <- c(sd.emotion,sd(as.numeric(relaxed.table[process,])))
   
   
  }
impossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequos
emotions.results.bh.correction$relaxed_p.value <- p.adjust(results, method="BH")
emotions.results.bh.correction$relaxed_mean.no.emotion <- mean.no.emotion
emotions.results.bh.correction$relaxed_mean.emotion <- mean.emotion
emotions.results.bh.correction$relaxed_sd.no.emotion <- sd.no.emotion
emotions.results.bh.correction$relaxed_sd.emotion <- sd.emotion

confident

results <- c()
mean.no.emotion <- c()
mean.emotion <- c()
sd.no.emotion <- c()
sd.emotion <- c()
 for (process in collaborative.processes)
   {
   
   results <- c(results, wilcox.test(t(confident.table[process,]),t(non.confident.table[process,]))$p.value)
   mean.no.emotion <- c(mean.no.emotion,mean(as.numeric(non.confident.table[process,])))
   mean.emotion <- c(mean.emotion,mean(as.numeric(confident.table[process,])))
   sd.no.emotion <- c(sd.no.emotion,sd(as.numeric(non.confident.table[process,])))
   sd.emotion <- c(sd.emotion,sd(as.numeric(confident.table[process,])))
  }
impossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequos
emotions.results.bh.correction$confident_p.value <- p.adjust(results, method="BH")
emotions.results.bh.correction$confident_mean.no.emotion <- mean.no.emotion
emotions.results.bh.correction$confident_mean.emotion <- mean.emotion
emotions.results.bh.correction$confident_sd.no.emotion <- sd.no.emotion
emotions.results.bh.correction$confident_sd.emotion <- sd.emotion

confused

results <- c()
mean.no.emotion <- c()
mean.emotion <- c()
sd.no.emotion <- c()
sd.emotion <- c()
 for (process in collaborative.processes)
   {
   
   results <- c(results, wilcox.test(t(confused.table[process,]),t(non.confused.table[process,]))$p.value)
   mean.no.emotion <- c(mean.no.emotion,mean(as.numeric(non.confused.table[process,])))
   mean.emotion <- c(mean.emotion,mean(as.numeric(confused.table[process,])))
   sd.no.emotion <- c(sd.no.emotion,sd(as.numeric(non.confused.table[process,])))
   sd.emotion <- c(sd.emotion,sd(as.numeric(confused.table[process,])))
   
  }
impossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequosimpossible de calculer la p-value exacte avec des ex-aequos
emotions.results.bh.correction$confused_p.value <- p.adjust(results, method="BH")
emotions.results.bh.correction$confused_mean.no.emotion <- mean.no.emotion
emotions.results.bh.correction$confused_mean.emotion <- mean.emotion
emotions.results.bh.correction$confused_sd.no.emotion <- sd.no.emotion
emotions.results.bh.correction$confused_sd.emotion <- sd.emotion

emotions.results.bh.correction

Export

#Exporting results in .xlsx file

write.xlsx(emotions.results.permutation.correction, paste0("results_receiver_meaningful_acts",toString(max.window.size),".xlsx")) 
LS0tDQp0aXRsZTogIjxiPiBFQVRNSU5UMSAtIFNoYXJpbmcgZW1vdGlvbnMgY29udHJpYnV0ZXMgdG8gcmVndWxhdGluZyBjb2xsYWJvcmF0aXZlIGludGVudGlvbnMgaW4gZ3JvdXAgcHJvYmxlbS1zb2x2aW5nIDxicj48Yj4iDQpzdWJ0aXRsZTogIjxiPkFuYWx5c2lzIDIgOiBjaGFuZ2VzIGluIHJlY2VpdmVyJ3MgY29sbGFib3JhdGl2ZSBhY3RzIGZvbGxvd2luZyB0aGUgc2hhcmluZyBvZiBlbWl0dGVyJ3MgZW1vdGlvbmFsIGxhYmVsczwvYj4iDQphdXRob3I6ICJTdW5ueSBBdnJ5Ig0KZGF0ZTogIkp1bHkgMTd0aCwgMjAxOSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCiAgICB0b2M6IHRydWUNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgDQotLS0NCg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCg0KaDEudGl0bGUgew0KICBmb250LXNpemU6IDMwcHg7DQp9DQo8L3N0eWxlPg0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeSh4bHN4KTtsaWJyYXJ5KGRwbHlyKTtsaWJyYXJ5KGx1YnJpZGF0ZSkNCmBgYA0KDQpgYGB7cn0NCm9wdGlvbnMoc2NpcGVuPTk5OSkgI3JlbW92ZSBzY2llbnRpZmljIG5vdGF0aW9uDQpkYXRhIDwtIHJlYWQuY3N2MigidGF1eF91dGlsaXNhdGlvbl9hY3Rlcy5jc3YiKQ0KZGF0YV9lYXQgPC0gZGF0YVtkYXRhJGVhdCA9PSAiT3VpIixdDQpkYXRhX2VhdA0KYGBgDQoNCiMjIEdsb2JhbCB2YXJpYWJsZXMNCmBgYHtyfQ0KI3dpbmRvdyBzaXplDQptYXgud2luZG93LnNpemUgPC0gNSAjc2l6ZSBvZiB0aGUgd2luZG93ID0gbnVtYmVyIG9mIGNvbGxhYm9yYXRpdmUgYWN0cyBwZXIgd2luZG93DQptYXgud2luZG93LnNpemUNCg0KI2R5YWQgaGF2aW5nIHVzZWQgdGhlIGVtb3Rpb24gYXdhcmVuZXNzIHRvb2wgKGVhdCBjb25kaXRpb24pIGZvciBzaGFyaW5nIHRoZWlyIGVtb3Rpb25zIA0KZHlhZHNfZWF0IDwtIGMoDQoiRDAyIiwNCiJEMDUiLA0KIkQwNyIsDQoiRDA5IiwNCiJEMTMiLA0KIkQxNiIsDQoiRDIxIiwNCiJEMjMiLA0KIkQyNiIsDQoiRDI3IiwNCiJEMjkiKQ0KDQojcGFydGljaXBhbnRzIGluIGVhdCBjb25kaXRpb24NCnBhcnRpY2lwYW50c19lYXQgPC0gYygNCiJEMDJQMDEiLA0KIkQwMlAwMiIsDQoiRDA1UDAxIiwNCiJEMDVQMDIiLA0KIkQwN1AwMSIsDQoiRDA3UDAyIiwNCiJEMDlQMDEiLA0KIkQwOVAwMiIsDQoiRDEzUDAxIiwNCiJEMTNQMDIiLA0KIkQxNlAwMSIsDQoiRDE2UDAyIiwNCiJEMjFQMDEiLA0KIkQyMVAwMiIsDQoiRDIzUDAxIiwNCiJEMjNQMDIiLA0KIkQyNlAwMSIsDQoiRDI2UDAyIiwNCiJEMjdQMDEiLA0KIkQyN1AwMiIsDQoiRDI5UDAxIiwNCiJEMjlQMDIiKQ0KDQojcGFydGljaXBhbnRzIGluIG5vLWVhdCBjb25kaXRpb24NCnBhcnRpY2lwYW50c19ub19lYXQgPC0gYygNCiJEMDRQMDEiLA0KIkQwNFAwMiIsDQoiRDA2UDAxIiwNCiJEMDZQMDIiLA0KIkQwOFAwMSIsDQoiRDA4UDAyIiwNCiJEMTBQMDEiLA0KIkQxMFAwMiIsDQoiRDEyUDAxIiwNCiJEMTJQMDIiLA0KIkQxNVAwMSIsDQoiRDE1UDAyIiwNCiJEMjBQMDEiLA0KIkQyMFAwMiIsDQoiRDI0UDAxIiwNCiJEMjRQMDIiKQ0KDQojICNlbW90aW9ucyBkaXNwbGF5ZWQgZHVyaW5nIHRoZSBjb2xsYWJvcmF0aXZlIHByb2JsZW0tc29sdmluZw0KIyBlbW90aW9ucyA8LSBjKA0KIyAiaW50ZXJlc3RlZCIsDQojICJmb2N1c2VkIiwNCiMgImRlbGlnaHRlZCIsDQojICJzYXRpc2ZpZWQiLA0KIyAiY29uZmlkZW50IiwNCiMgImFtdXNlZCIsDQojICJyZWxpZXZlZCIsDQojICJyZWxheGVkIiwNCiMgImNvbmZ1c2VkIiwNCiMgInN0cmVzc2VkIiwNCiMgImRpc3NhdGlzZmllZCIsDQojICJhbm5veWVkIiwNCiMgImZydXN0cmF0ZWQiLA0KIyAiZ3JhdGVmdWwiLA0KIyAiZGlzYXBwb2ludGVkIiwNCiMgImVtcGF0aGljIiwNCiMgImJvcmVkIiwNCiMgInN1cnByaXNlZCIsDQojICJwdXp6bGVkIiwNCiMgImFueGlvdXMiLA0KIyAiaW1wYXRpZW50IikNCg0KI0FsbCBjb2xsYWJvcmF0aXZlIGFjdHMgZW1pdHRlZCBieSBwYXJ0aWNpcGFudHMNCg0KIyBjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyA8LSBjKA0KIyAiYWNjZXB0IiwNCiMgImFncmVlIiwNCiMgImNoZWNrLmNvbXByZWhlbnNpb24iLA0KIyAiY2hlY2sucmVjZXB0aW9uIiwNCiMgImNvb3JkaW5hdGUudGVhbXdvcmsiLA0KIyAiZGlzYWdyZWUiLA0KIyAiZWxpY2l0Lm9waW5pb24iLA0KIyAiZWxpY2l0LnBhcnRuZXIuaW5mb3JtYXRpb24iLA0KIyAiZWxpY2l0LnByb3Bvc2l0aW9uIiwNCiMgImVsaWNpdC5yZWNhbGwiLA0KIyAiZWxpY2l0LnRhc2suaW5mb3JtYXRpb24iLA0KIyAiZ2l2ZS5leHBsYW5hdGlvbiIsDQojICJnaXZlLm9waW5pb24uYWdhaW5zdCIsDQojICJnaXZlLm9waW5pb24uZm9yIiwNCiMgImdpdmUucHJvcG9zaXRpb24iLA0KIyAiZ2l2ZS5yZWNhbGwiLA0KIyAiZ2l2ZS5zZWxmLmluZm9ybWF0aW9uIiwNCiMgImdpdmUudGFzay5pbmZvcm1hdGlvbiIsDQojICJpbmNvcnBvcmF0ZSIsDQojICJtYW5hZ2UudGFzayIsDQojICJvdGhlciIsDQojICJvdXRzaWRlLmFjdGl2aXR5IiwNCiMgInJlbGF4LmF0bW9zcGhlcmUiLA0KIyAic2hvdy5hY3RpdmUubGlzdGVuaW5nIiwNCiMgInNob3cucmVmbGVjdGlvbiIsDQojICJzaG93Lmhvc3RpbGl0eSIsDQojICJzaG93LnNvbGlkYXJpdHkiLA0KIyAidG9vbC5kaXNjb3Vyc2UiLA0KIyAidXNlLnNvY2lhbC5jb252ZW50aW9uIikNCmBgYA0KDQpgYGB7cn0NCiNBbGwgY29sbGFib3JhdGl2ZSBhY3RzIGVtaXR0ZWQgYnkgcGFydGljaXBhbnRzIHJlcHJlc2VudGluZyBhdCBsZWFzdCA0IHBlcmNlbnRzIG9mIHRoZSB0b3RhbA0KDQpjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyA8LSBjKA0KImFjY2VwdCIsDQoiYWdyZWUiLA0KImdpdmUub3Bpbmlvbi5mb3IiLA0KImdpdmUucHJvcG9zaXRpb24iLA0KImdpdmUuc2VsZi5pbmZvcm1hdGlvbiIsDQoiZ2l2ZS50YXNrLmluZm9ybWF0aW9uIiwNCiJtYW5hZ2UudGFzayIsDQoicmVsYXguYXRtb3NwaGVyZSIsDQoic2hvdy5yZWZsZWN0aW9uIiwNCiJ0b29sLmRpc2NvdXJzZSIpDQoNCg0KI2Vtb3Rpb25zIGRpc3BsYXllZCBkdXJpbmcgdGhlIGNvbGxhYm9yYXRpdmUgcHJvYmxlbS1zb2x2aW5nIHJlcHJlc2VudGF0aW5nIGF0IGxlYXN0IA0KZW1vdGlvbnMgPC0gYygNCiJpbnRlcmVzdGVkIiwNCiJmb2N1c2VkIiwNCiJkZWxpZ2h0ZWQiLA0KInNhdGlzZmllZCIsDQoiYW11c2VkIiwNCiJyZWxheGVkIikNCmBgYA0KDQpJZiB0aGVyZSBpcyBub3QgYXQgbGVhc3QgKG1heC53aW5kb3cuc2l6ZSkgY29sbGFib3JhdGl2ZSBwcm9jZXNzZXMgZm9sbG93aW5nIHRoZSBlbW90aW9uIG9mIGludGVyZXN0IC0+IHRoaXMgb2NjdXJlbmNlIGlzIG5vdCB0YWtlbiBpbnRvIGFjY291bnQgZm9yIHRoZSBjb21wdXRhdGlvbiBvZiB0aGUgcmVsYXRpdmUgdXNlDQoNCklmIGFuIGVtb3Rpb24gb3ZlcmxhcHMgd2l0aCBvbmUgYW5vdGhlciAoaS5lLiwgYSBuZXcgc2FtZSBlbW90aW9uKSBpcyBtZXQgYmVmb3JlIChtYXgud2luZG93LnNpemUpIGlzIHJlYWNoZWQsIHRoaXMgbGF0ZXN0IG9jY3VyZW5jZSBpcyBub3QgdGFrZW4gaW50byBhY2NvdW50IGZvciB0aGUgY29tcHVhdGlvbiBvZiB0aGUgcmVsYXRpdmUgdXNlDQoNCiMjIFJUVSBjb21wdXRhdGlvbg0KDQojIyMgSW50ZXJlc3RlZA0KYGBge3J9DQojRmluZCBjYXNlcyBhdmFpbGFibGUgKHBhcnRpY2lwYW50cyB0aGF0IGhhdmUgc2hhcmVkIHRoZSBlbW90aW9uKQ0KaW50ZXJlc3RlZC5jYXNlcyA8LSBjKCkNCg0KZW1vdGlvbiA9ICJpbnRlcmVzdGVkIg0KZm9yIChwYXJ0aWNpcGFudCBpbiBwYXJ0aWNpcGFudHNfZWF0KSB7DQogICAgcHJpbnQocGFzdGUoIlBvdXIgbGUgcGFydGljaXBhbnQgIiwgcGFydGljaXBhbnQsIiBpbCB5IGEiLCBsZW5ndGgoZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhcnRpY2lwYW50ICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSBlbW90aW9uKSxjKCJzaGFyZWQuZW1vdGlvbiIpXSksImNvcnJlc3BvbmRhbmNlKHMpIikpDQogICAgaW50ZXJlc3RlZC5jYXNlc1twYXJ0aWNpcGFudF0gPC0gbGVuZ3RoKGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXJ0aWNpcGFudCAmIGRhdGEkc2hhcmVkLmVtb3Rpb24gPT0gZW1vdGlvbiksYygic2hhcmVkLmVtb3Rpb24iKV0pDQp9DQoNCmludGVyZXN0ZWQuYXZhaWxhYmxlLmNhc2VzIDwtIGludGVyZXN0ZWQuY2FzZXNbaW50ZXJlc3RlZC5jYXNlcyAhPSAwXQ0KaW50ZXJlc3RlZC5hdmFpbGFibGUuY2FzZXMNCmxlbmd0aChpbnRlcmVzdGVkLmF2YWlsYWJsZS5jYXNlcykNCm5hbWVzKGludGVyZXN0ZWQuYXZhaWxhYmxlLmNhc2VzKQ0KYGBgDQoNCmBgYHtyfQ0KI2ludGVyZXN0ZWQgc2FtcGxlDQpwYXJ0aWNpcGFudHNfZWF0X2ludGVyZXN0ZWRfUDAxIDwtIGMoIkQwMlAwMSIsIkQwN1AwMSIsIkQwOVAwMSIsIkQxM1AwMSIsIkQxNlAwMSIsIkQyMVAwMSIsIkQyM1AwMSIsIkQyNlAwMSIsIkQyOVAwMSIpDQpwYXJ0aWNpcGFudHNfZWF0X2ludGVyZXN0ZWRfUDAyIDwtIGMoIkQwMlAwMiIsIkQwNVAwMiIsIkQwN1AwMiIsIkQwOVAwMiIsIkQxM1AwMiIsIkQxNlAwMiIsIkQyMVAwMiIsIkQyM1AwMiIsIkQyN1AwMiIsIkQyOVAwMiIpDQpgYGANCg0KYGBge3J9DQojQ29tcHV0ZSB0aGUgcmVhbC10aW1lIHVzZSBmb3IgdGhlIGVtb3Rpb24gaW50ZXJlc3RlZA0KDQojc2VsZWN0IHRoZSBzdWJzZXQgb2YgY29sbGFib3JhdGl2ZSBwcm9jZXNzZXMgZm9yIGEgZ2l2ZW4gcGFydGljaXBhbnQuIEZvciB0aGUgZW1vdGlvbiBpbnRlcmVzdGVkLCB0aGUgKG1heC53aW5kb3dzLnNpemUpIGNvbGxhYm9yYXRpdmUgcHJvY2Vzc2VzIG9mIHRoZSBvdGhlcidzIHBhcnRuZXIgZnJvbSB0aGUgc2FtZSBkeWFkIGFyZSBzZWxlY3RlZA0KDQojUDAyIHBhcnRpY2lwYW50cw0KbiA8LSBtYXRyaXgoZGF0YT1OQSxucm93PWxlbmd0aChjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyksbmNvbD0wKQ0KaW50ZXJlc3RlZC50YWJsZS5wMiA8LSBkYXRhLmZyYW1lKG4pDQpyb3duYW1lcyhpbnRlcmVzdGVkLnRhYmxlLnAyKSA8LSBjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcw0KDQpmb3IgKHAgaW4gcGFydGljaXBhbnRzX2VhdF9pbnRlcmVzdGVkX1AwMSkNCnsNCiAgbSA8LSBtYXRyaXgoZGF0YT1OQSxucm93PW1heC53aW5kb3cuc2l6ZSxuY29sPTApDQogIGludGVyZXN0ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUgPC0gZGF0YS5mcmFtZShtKQ0KDQogIGludGVyZXN0ZWQudGltZXMgPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHAgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09ImludGVyZXN0ZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgaW50ZXJlc3RlZC50aW1lcy5sZW5ndGggPC0gbGVuZ3RoKGludGVyZXN0ZWQudGltZXMpDQoNCiAgZm9yIChpIGluIHNlcSgxOmxlbmd0aChpbnRlcmVzdGVkLnRpbWVzKSkpDQogIHsNCiAgICBpbnRlcmVzdGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlWyxwYXN0ZTAoIm9jY3VyZW5jZSIsaSldIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIyIikgJiBkYXRhJHVuaXgudGltZS52aWRlbyA+IGludGVyZXN0ZWQudGltZXNbaV0pLGMoImNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzIildWzE6bWF4LndpbmRvdy5zaXplXSANCiAgfQ0KDQogIGludGVyZXN0ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUNCiAgI2NoZWNrIGlmIHRoZSBlbW90aW9uIHdpbmRvd3MgYWxsIGhhdmUgYSBsZW5ndGggb2YgbWF4LndpbmRvdy5zaXplDQogICN3aGVuIGl0IGlzIG5vdCB0aGUgY2FzZSwgdGhlIGVtb3Rpb24gd2luZG93IGlzIHJlbW92ZWQNCiAgZm9yIChjb2wgaW4gY29sbmFtZXMoaW50ZXJlc3RlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkpew0KICAgIGlmIChhbnlOQShpbnRlcmVzdGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlWyxjb2xdKSkgew0KICAgICAgaW50ZXJlc3RlZC50aW1lcy5sZW5ndGggPC0gaW50ZXJlc3RlZC50aW1lcy5sZW5ndGgtMQ0KICAgICAgaW50ZXJlc3RlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSA9IGludGVyZXN0ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLCEobmFtZXMoaW50ZXJlc3RlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkgJWluJSBjKGNvbCkpXQ0KICAgIH0NCiAgfQ0KICANCiAgI2NvbXB1dGUgdGhlIHJlYWwtdGltZSB1c2UgZm9yIGV2ZXJ5IGNvbGxhYm9yYXRpdmUgcHJvY2Vzcw0KICB4IDwtIGMoKQ0KICBmb3IgKGkgaW4gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpDQogIHsNCiAgICB4W2ldIDwtIGxlbmd0aChpbnRlcmVzdGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlW2ludGVyZXN0ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUgPT0gaV0pDQogIH0NCiAgeCA8LSB4L2ludGVyZXN0ZWQudGltZXMubGVuZ3RoICNudW1iZXIgb2YgZW1vdGlvbiB3aW5kb3dzDQogIGludGVyZXN0ZWQudGFibGUucDJbLHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjIiKV0gPSB4DQp9DQoNCmludGVyZXN0ZWQudGFibGUucDINCg0KI1AwMSBwYXJ0aWNpcGFudHMNCm4gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1sZW5ndGgoY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpLG5jb2w9MCkNCmludGVyZXN0ZWQudGFibGUucDEgPC0gZGF0YS5mcmFtZShuKQ0Kcm93bmFtZXMoaW50ZXJlc3RlZC50YWJsZS5wMSkgPC0gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfaW50ZXJlc3RlZF9QMDIpDQp7DQogIG0gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1tYXgud2luZG93LnNpemUsbmNvbD0wKQ0KICBpbnRlcmVzdGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlIDwtIGRhdGEuZnJhbWUobSkNCg0KICBpbnRlcmVzdGVkLnRpbWVzIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSAiaW50ZXJlc3RlZCIpLGMoInVuaXgudGltZS52aWRlbyIpXQ0KICBpbnRlcmVzdGVkLnRpbWVzLmxlbmd0aCA8LSBsZW5ndGgoaW50ZXJlc3RlZC50aW1lcykNCiAgDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgoaW50ZXJlc3RlZC50aW1lcykpKQ0KICB7DQogICAgaW50ZXJlc3RlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVsscGFzdGUwKCJvY2N1cmVuY2UiLGkpXSA8LSBkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMSIpICYgZGF0YSR1bml4LnRpbWUudmlkZW8gPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnRlcmVzdGVkLnRpbWVzW2ldKSxjKCJjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyIpXVsxOm1heC53aW5kb3cuc2l6ZV0gDQogIH0NCg0KICBpbnRlcmVzdGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlDQogIA0KICAjY2hlY2sgaWYgdGhlIGVtb3Rpb24gd2luZG93cyBhbGwgaGF2ZSBhIGxlbmd0aCBvZiBtYXgud2luZG93LnNpemUNCiAgI3doZW4gaXQgaXMgbm90IHRoZSBjYXNlLCB0aGUgZW1vdGlvbiB3aW5kb3cgaXMgcmVtb3ZlZA0KICBmb3IgKGNvbCBpbiBjb2xuYW1lcyhpbnRlcmVzdGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlKSl7DQogICAgaWYgKGFueU5BKGludGVyZXN0ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLGNvbF0pKSB7DQogICAgICBpbnRlcmVzdGVkLnRpbWVzLmxlbmd0aCA8LSBpbnRlcmVzdGVkLnRpbWVzLmxlbmd0aC0xDQogICAgICBpbnRlcmVzdGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlID0gaW50ZXJlc3RlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVssIShuYW1lcyhpbnRlcmVzdGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlKSAlaW4lIGMoY29sKSldDQogICAgfQ0KICB9DQogIA0KICAjY29tcHV0ZSB0aGUgcmVhbC10aW1lIHVzZSBmb3IgZXZlcnkgY29sbGFib3JhdGl2ZSBwcm9jZXNzDQogIHggPC0gYygpDQogIGZvciAoaSBpbiBjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcykNCiAgew0KICAgIHhbaV0gPC0gbGVuZ3RoKGludGVyZXN0ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbaW50ZXJlc3RlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSA9PSBpXSkNCiAgfQ0KICB4IDwtIHgvaW50ZXJlc3RlZC50aW1lcy5sZW5ndGggI251bWJlciBvZiBlbW90aW9uIHdpbmRvd3MNCiAgaW50ZXJlc3RlZC50YWJsZS5wMVsscGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMSIpXSA9IHgNCn0NCg0KaW50ZXJlc3RlZC50YWJsZS5wMSAgICANCg0KaW50ZXJlc3RlZC50YWJsZSA8LSBjYmluZChpbnRlcmVzdGVkLnRhYmxlLnAxLCBpbnRlcmVzdGVkLnRhYmxlLnAyKQ0KaW50ZXJlc3RlZC50YWJsZQ0KYGBgDQoNCg0KYGBge3J9DQojQ29tcHV0ZSB0aGUgcmVhbC10aW1lIHdoZW4gbm8gZW1vdGlvbiBpbnRlcmVzdGVkDQoNCiNTZWxlY3QgYSBzdWJzZXQgb2YgdGhlIGRhdGEgbm90IGluY2x1ZGluZyB0aGUgZW1vdGlvbiB3aW5kb3dzDQoNCiNQMDIgcGFydGljaXBhbnRzDQpuIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bGVuZ3RoKGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSxuY29sPTApDQpub24uaW50ZXJlc3RlZC50YWJsZS5wMiA8LSBkYXRhLmZyYW1lKG4pDQpyb3duYW1lcyhub24uaW50ZXJlc3RlZC50YWJsZS5wMikgPC0gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfaW50ZXJlc3RlZF9QMDEpDQp7DQogIGludGVyZXN0ZWQudGltZXMgPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHAgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09ImludGVyZXN0ZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgdG8uYmUuZHJvcHBlZCA8LSB2ZWN0b3IoKQ0KICANCiAgZm9yIChpIGluIHNlcSgxOmxlbmd0aChpbnRlcmVzdGVkLnRpbWVzKSkpDQogIHsNCiAgICB0by5iZS5kcm9wcGVkIDwtIGModG8uYmUuZHJvcHBlZCwgd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIyIikgJiBkYXRhJHVuaXgudGltZS52aWRlbyA+IGludGVyZXN0ZWQudGltZXNbaV0pWzE6bWF4LndpbmRvdy5zaXplXSkNCiAgfQ0KICANCiAgI3JlbW92ZSBOQSB3aGVuIG1heC53aW5kb3cuc2l6ZSBnb2VzIG91dCBvZiBib3VuZHMgYmVjYXVzZSB0aGUgZW5kIG9mIGNvbGxhYm9yYXRpdmUgYWN0cyBmb3IgdGhhdCBwYXJ0aWNpcGFudCBpcyByZWFjaGVkDQogIHRvLmJlLmRyb3BwZWQgPC0gdG8uYmUuZHJvcHBlZFshaXMubmEodG8uYmUuZHJvcHBlZCldIA0KICBkYXRhLmtlcHQgPC0gZGF0YVstdG8uYmUuZHJvcHBlZCxdICNkYXRhLmtlcHQgaXMgdGhlIGRhdGEgd2l0aG91dCBlbW90aW9uIHdpbmRvd3MNCiAgDQogIGRhdGEua2VwdCA8LSBkYXRhLmtlcHRbZGF0YS5rZXB0JHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjIiKSxdDQogIA0KICAjS2VlcCBhIG51bWJlciBvZiBsaW5lcyB0aGF0IGlzIGEgbXVsdGlwbGUgb2YgbWF4LndpbmRvd3Muc2l6ZSA9IG51bWJlciBvZiBuby1lbW90aW9uIHdpbmRvd3MNCiAgbiA8LSBucm93KGRhdGEua2VwdCkNCiAgZGF0YS5rZXB0IDwtIGRhdGEua2VwdFtjKDE6KG4tKG4lJW1heC53aW5kb3cuc2l6ZSkpKSxdDQogIA0KICBsZW5ndGgoZGF0YS5rZXB0JHBhcnRpY2lwYW50KQ0KICANCiAgcmVzdWx0cyA8LSBjKCkNCiAgZm9yIChwcm9jZXNzIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKQ0KICAgIHsNCiAgICByZXN1bHRzIDwtIGMocmVzdWx0cywgc3VtKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcz09cHJvY2VzcykpDQogICAgfQ0KICANCiAgbm9uLmludGVyZXN0ZWQudGFibGUucDJbLHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjIiKV0gPC0gcmVzdWx0cy8obGVuZ3RoKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyklLyVtYXgud2luZG93LnNpemUpDQogIHJlc3VsdHMgPC0gYygpDQogIA0KfQ0KDQpub24uaW50ZXJlc3RlZC50YWJsZS5wMg0KDQojUDAxIHBhcnRpY2lwYW50cw0KbiA8LSBtYXRyaXgoZGF0YT1OQSxucm93PWxlbmd0aChjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyksbmNvbD0wKQ0Kbm9uLmludGVyZXN0ZWQudGFibGUucDEgPC0gZGF0YS5mcmFtZShuKQ0Kcm93bmFtZXMobm9uLmludGVyZXN0ZWQudGFibGUucDEpIDwtIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzDQoNCmZvciAocCBpbiBwYXJ0aWNpcGFudHNfZWF0X2ludGVyZXN0ZWRfUDAyKQ0Kew0KICBpbnRlcmVzdGVkLnRpbWVzIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSJpbnRlcmVzdGVkIiksYygidW5peC50aW1lLnZpZGVvIildDQogIA0KICB0by5iZS5kcm9wcGVkIDwtIHZlY3RvcigpDQogIA0KICBmb3IgKGkgaW4gc2VxKDE6bGVuZ3RoKGludGVyZXN0ZWQudGltZXMpKSkNCiAgew0KICAgIHRvLmJlLmRyb3BwZWQgPC0gYyh0by5iZS5kcm9wcGVkLCB3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKSAmIGRhdGEkdW5peC50aW1lLnZpZGVvID4gaW50ZXJlc3RlZC50aW1lc1tpXSlbMTptYXgud2luZG93LnNpemVdKQ0KICAgIA0KICB9DQogIA0KICAjcmVtb3ZlIE5BIHdoZW4gbWF4LndpbmRvdy5zaXplIGdvZXMgb3V0IG9mIGJvdW5kcyBiZWNhdXNlIHRoZSBlbmQgb2YgY29sbGFib3JhdGl2ZSBhY3RzIGZvciB0aGF0IHBhcnRpY2lwYW50IGlzIHJlYWNoZWQNCiAgdG8uYmUuZHJvcHBlZCA8LSB0by5iZS5kcm9wcGVkWyFpcy5uYSh0by5iZS5kcm9wcGVkKV0NCiAgDQogIGRhdGEua2VwdCA8LSBkYXRhWy10by5iZS5kcm9wcGVkLF0gI2RhdGEua2VwdCBpcyB0aGUgZGF0YSB3aXRob3V0IGVtb3Rpb24gd2luZG93cw0KICANCiAgcHJpbnQoZGF0YS5rZXB0KQ0KICANCiAgZGF0YS5rZXB0IDwtIGRhdGEua2VwdFtkYXRhLmtlcHQkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMSIpLF0NCiAgDQogICNrZWVwIGEgbnVtYmVyIG9mIGxpbmVzIHRoYXQgaXMgYSBtdWx0aXBsZSBvZiBtYXgud2luZG93cy5zaXplID0gbnVtYmVyIG9mIG5vLWVtb3Rpb24gd2luZG93DQogIG4gPC0gbnJvdyhkYXRhLmtlcHQpDQogIGRhdGEua2VwdCA8LSBkYXRhLmtlcHRbYygxOihuLShuJSVtYXgud2luZG93LnNpemUpKSksXQ0KICANCiAgcmVzdWx0cyA8LSBjKCkNCiAgZm9yIChwcm9jZXNzIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKQ0KICAgIHsNCiAgICByZXN1bHRzIDwtIGMocmVzdWx0cywgc3VtKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcz09cHJvY2VzcykpDQogICAgfQ0KICANCiAgbm9uLmludGVyZXN0ZWQudGFibGUucDFbLHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKV0gPC0gcmVzdWx0cy8obGVuZ3RoKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyklLyVtYXgud2luZG93LnNpemUpDQogIHJlc3VsdHMgPC0gYygpDQogIA0KfQ0KDQpub24uaW50ZXJlc3RlZC50YWJsZS5wMQ0KDQpub24uaW50ZXJlc3RlZC50YWJsZSA8LSBjYmluZChub24uaW50ZXJlc3RlZC50YWJsZS5wMSwgbm9uLmludGVyZXN0ZWQudGFibGUucDIpDQpub24uaW50ZXJlc3RlZC50YWJsZQ0KDQpmb3IgKGNvbCBpbiBjb2xuYW1lcyhub24uaW50ZXJlc3RlZC50YWJsZSkpew0KICAgIHByaW50KHN1bShub24uaW50ZXJlc3RlZC50YWJsZVssY29sXSkpIA0KfQ0KYGBgDQoNCiMjIyBGb2N1c2VkDQoNCmBgYHtyfQ0KI0ZpbmQgY2FzZXMgYXZhaWxhYmxlIGZvciBmb2N1c2VkDQoNCmZvY3VzZWQuY2FzZXMgPC0gYygpDQoNCmVtb3Rpb24gPSAiZm9jdXNlZCINCmZvciAocGFydGljaXBhbnQgaW4gcGFydGljaXBhbnRzX2VhdCkgew0KICAgIHByaW50KHBhc3RlKCJQb3VyIGxlIHBhcnRpY2lwYW50ICIsIHBhcnRpY2lwYW50LCIgaWwgeSBhIiwgbGVuZ3RoKGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXJ0aWNpcGFudCAmIGRhdGEkc2hhcmVkLmVtb3Rpb24gPT0gZW1vdGlvbiksYygic2hhcmVkLmVtb3Rpb24iKV0pLCJjb3JyZXNwb25kYW5jZShzKSIpKQ0KICAgIGZvY3VzZWQuY2FzZXNbcGFydGljaXBhbnRdIDwtIGxlbmd0aChkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcGFydGljaXBhbnQgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09IGVtb3Rpb24pLGMoInNoYXJlZC5lbW90aW9uIildKQ0KfQ0KDQpmb2N1c2VkLmF2YWlsYWJsZS5jYXNlcyA8LSBmb2N1c2VkLmNhc2VzW2ZvY3VzZWQuY2FzZXMgIT0gMF0NCmZvY3VzZWQuYXZhaWxhYmxlLmNhc2VzDQpsZW5ndGgoZm9jdXNlZC5hdmFpbGFibGUuY2FzZXMpDQpuYW1lcyhmb2N1c2VkLmF2YWlsYWJsZS5jYXNlcykNCg0KYGBgDQpgYGB7cn0NCiNmb2N1c2VkIHNhbXBsZQ0KcGFydGljaXBhbnRzX2VhdF9mb2N1c2VkX1AwMSA8LSBjKCJEMDJQMDEiLCJEMDdQMDEiLCJEMDdQMDEiLCJEMDlQMDEiLCJEMTNQMDEiLCJEMTZQMDEiLCJEMjFQMDEiLCJEMjNQMDEiLCJEMjZQMDEiLCJEMjdQMDEiKQ0KcGFydGljaXBhbnRzX2VhdF9mb2N1c2VkX1AwMiA8LSBjKCJEMDJQMDIiLCJEMDVQMDIiLCJEMDdQMDIiLCJEMDlQMDIiLCJEMTNQMDIiLCJEMTZQMDIiLCJEMjFQMDIiLCJEMjNQMDIiLCJEMjZQMDIiLCJEMjdQMDIiLCJEMjlQMDIiKQ0KYGBgDQoNCmBgYHtyfQ0KI0NvbXB1dGUgdGhlIHJlYWwtdGltZSB1c2UgZm9yIHRoZSBlbW90aW9uIGZvY3VzZWQNCg0KI3NlbGVjdCB0aGUgc3Vic2V0IG9mIGNvbGxhYm9yYXRpdmUgcHJvY2Vzc2VzIGZvciBhIGdpdmVuIHBhcnRpY2lwYW50LiBGb3IgdGhlIGVtb3Rpb24gZm9jdXNlZCwgdGhlIChtYXgud2luZG93cy5zaXplKSBjb2xsYWJvcmF0aXZlIHByb2Nlc3NlcyBvZiB0aGUgb3RoZXIncyBwYXJ0bmVyIGZyb20gdGhlIHNhbWUgZHlhZCBhcmUgc2VsZWN0ZWQNCg0KI1AwMiBwYXJ0aWNpcGFudHMNCm4gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1sZW5ndGgoY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpLG5jb2w9MCkNCmZvY3VzZWQudGFibGUucDIgPC0gZGF0YS5mcmFtZShuKQ0Kcm93bmFtZXMoZm9jdXNlZC50YWJsZS5wMikgPC0gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfZm9jdXNlZF9QMDEpDQp7DQogIG0gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1tYXgud2luZG93LnNpemUsbmNvbD0wKQ0KICBmb2N1c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlIDwtIGRhdGEuZnJhbWUobSkNCg0KICBmb2N1c2VkLnRpbWVzIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSJmb2N1c2VkIiksYygidW5peC50aW1lLnZpZGVvIildDQogIGZvY3VzZWQudGltZXMubGVuZ3RoIDwtIGxlbmd0aChmb2N1c2VkLnRpbWVzKQ0KDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgoZm9jdXNlZC50aW1lcykpKQ0KICB7DQogICAgZm9jdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVsscGFzdGUwKCJvY2N1cmVuY2UiLGkpXSA8LSBkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMiIpICYgZGF0YSR1bml4LnRpbWUudmlkZW8gPiBmb2N1c2VkLnRpbWVzW2ldKSxjKCJjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyIpXVsxOm1heC53aW5kb3cuc2l6ZV0gDQogIH0NCg0KICBmb2N1c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlDQogICNjaGVjayBpZiB0aGUgZW1vdGlvbiB3aW5kb3dzIGFsbCBoYXZlIGEgbGVuZ3RoIG9mIG1heC53aW5kb3cuc2l6ZQ0KICAjd2hlbiBpdCBpcyBub3QgdGhlIGNhc2UsIHRoZSBlbW90aW9uIHdpbmRvdyBpcyByZW1vdmVkDQogIGZvciAoY29sIGluIGNvbG5hbWVzKGZvY3VzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUpKXsNCiAgICBpZiAoYW55TkEoZm9jdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVssY29sXSkpIHsNCiAgICAgIGZvY3VzZWQudGltZXMubGVuZ3RoIDwtIGZvY3VzZWQudGltZXMubGVuZ3RoLTENCiAgICAgIGZvY3VzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUgPSBmb2N1c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlWywhKG5hbWVzKGZvY3VzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUpICVpbiUgYyhjb2wpKV0NCiAgICB9DQogIH0NCiAgDQogICNjb21wdXRlIHRoZSByZWFsLXRpbWUgdXNlIGZvciBldmVyeSBjb2xsYWJvcmF0aXZlIHByb2Nlc3MNCiAgeCA8LSBjKCkNCiAgZm9yIChpIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKQ0KICB7DQogICAgeFtpXSA8LSBsZW5ndGgoZm9jdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVtmb2N1c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlID09IGldKQ0KICB9DQogIHggPC0geC9mb2N1c2VkLnRpbWVzLmxlbmd0aCAjbnVtYmVyIG9mIGVtb3Rpb24gd2luZG93cw0KICBmb2N1c2VkLnRhYmxlLnAyWyxwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIyIildID0geA0KfQ0KDQpmb2N1c2VkLnRhYmxlLnAyDQoNCiNQMDEgcGFydGljaXBhbnRzDQpuIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bGVuZ3RoKGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSxuY29sPTApDQpmb2N1c2VkLnRhYmxlLnAxIDwtIGRhdGEuZnJhbWUobikNCnJvd25hbWVzKGZvY3VzZWQudGFibGUucDEpIDwtIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzDQoNCmZvciAocCBpbiBwYXJ0aWNpcGFudHNfZWF0X2ZvY3VzZWRfUDAyKQ0Kew0KICBtIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bWF4LndpbmRvdy5zaXplLG5jb2w9MCkNCiAgZm9jdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSA8LSBkYXRhLmZyYW1lKG0pDQoNCiAgZm9jdXNlZC50aW1lcyA8LSBkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcCAmIGRhdGEkc2hhcmVkLmVtb3Rpb24gPT0gImZvY3VzZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgZm9jdXNlZC50aW1lcy5sZW5ndGggPC0gbGVuZ3RoKGZvY3VzZWQudGltZXMpDQogIA0KICBmb3IgKGkgaW4gc2VxKDE6bGVuZ3RoKGZvY3VzZWQudGltZXMpKSkNCiAgew0KICAgIGZvY3VzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLHBhc3RlMCgib2NjdXJlbmNlIixpKV0gPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKSAmIGRhdGEkdW5peC50aW1lLnZpZGVvID4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9jdXNlZC50aW1lc1tpXSksYygiY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMiKV1bMTptYXgud2luZG93LnNpemVdIA0KICB9DQoNCiAgZm9jdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZQ0KICANCiAgI2NoZWNrIGlmIHRoZSBlbW90aW9uIHdpbmRvd3MgYWxsIGhhdmUgYSBsZW5ndGggb2YgbWF4LndpbmRvdy5zaXplDQogICN3aGVuIGl0IGlzIG5vdCB0aGUgY2FzZSwgdGhlIGVtb3Rpb24gd2luZG93IGlzIHJlbW92ZWQNCiAgZm9yIChjb2wgaW4gY29sbmFtZXMoZm9jdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkpew0KICAgIGlmIChhbnlOQShmb2N1c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlWyxjb2xdKSkgew0KICAgICAgZm9jdXNlZC50aW1lcy5sZW5ndGggPC0gZm9jdXNlZC50aW1lcy5sZW5ndGgtMQ0KICAgICAgZm9jdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSA9IGZvY3VzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLCEobmFtZXMoZm9jdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkgJWluJSBjKGNvbCkpXQ0KICAgIH0NCiAgfQ0KICANCiAgI2NvbXB1dGUgdGhlIHJlYWwtdGltZSB1c2UgZm9yIGV2ZXJ5IGNvbGxhYm9yYXRpdmUgcHJvY2Vzcw0KICB4IDwtIGMoKQ0KICBmb3IgKGkgaW4gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpDQogIHsNCiAgICB4W2ldIDwtIGxlbmd0aChmb2N1c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlW2ZvY3VzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUgPT0gaV0pDQogIH0NCiAgeCA8LSB4L2ZvY3VzZWQudGltZXMubGVuZ3RoICNudW1iZXIgb2YgZW1vdGlvbiB3aW5kb3dzDQogIGZvY3VzZWQudGFibGUucDFbLHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKV0gPSB4DQp9DQoNCmZvY3VzZWQudGFibGUucDEgICAgDQoNCmZvY3VzZWQudGFibGUgPC0gY2JpbmQoZm9jdXNlZC50YWJsZS5wMSwgZm9jdXNlZC50YWJsZS5wMikNCmZvY3VzZWQudGFibGUNCmBgYA0KDQpgYGB7cn0NCiNDb21wdXRlIHRoZSByZWFsLXRpbWUgdXNlIHdoZW4gbm8gZW1vdGlvbiBmb2N1c2VkDQoNCiNTZWxlY3QgYSBzdWJzZXQgb2YgdGhlIGRhdGEgbm90IGluY2x1ZGluZyB0aGUgZW1vdGlvbiB3aW5kb3dzDQoNCiNQMDIgcGFydGljaXBhbnRzDQpuIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bGVuZ3RoKGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSxuY29sPTApDQpub24uZm9jdXNlZC50YWJsZS5wMiA8LSBkYXRhLmZyYW1lKG4pDQpyb3duYW1lcyhub24uZm9jdXNlZC50YWJsZS5wMikgPC0gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfZm9jdXNlZF9QMDEpDQp7DQogIGZvY3VzZWQudGltZXMgPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHAgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09ImZvY3VzZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgDQogIHRvLmJlLmRyb3BwZWQgPC0gdmVjdG9yKCkNCiAgDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgoZm9jdXNlZC50aW1lcykpKQ0KICB7DQogICAgdG8uYmUuZHJvcHBlZCA8LSBjKHRvLmJlLmRyb3BwZWQsIHdoaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMiIpICYgZGF0YSR1bml4LnRpbWUudmlkZW8gPiBmb2N1c2VkLnRpbWVzW2ldKVsxOm1heC53aW5kb3cuc2l6ZV0pDQogICAgDQogIH0NCiAgDQogICNyZW1vdmUgTkEgd2hlbiBtYXgud2luZG93LnNpemUgZ29lcyBvdXQgb2YgYm91bmRzIGJlY2F1c2UgdGhlIGVuZCBvZiBjb2xsYWJvcmF0aXZlIGFjdHMgZm9yIHRoYXQgcGFydGljaXBhbnQgaXMgcmVhY2hlZA0KICB0by5iZS5kcm9wcGVkIDwtIHRvLmJlLmRyb3BwZWRbIWlzLm5hKHRvLmJlLmRyb3BwZWQpXSANCiAgDQogIGRhdGEua2VwdCA8LSBkYXRhWy10by5iZS5kcm9wcGVkLF0gI2RhdGEua2VwdCBpcyB0aGUgZGF0YSB3aXRob3V0IGVtb3Rpb25hbCBjaHVua3MNCiAgDQogIGRhdGEua2VwdCA8LSBkYXRhLmtlcHRbZGF0YS5rZXB0JHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjIiKSxdDQogIA0KICAjS2VlcCBhIG51bWJlciBvZiBsaW5lcyB0aGF0IGlzIGEgbXVsdGlwbGUgb2YgbWF4LndpbmRvd3Muc2l6ZSA9IG51bWJlciBvZiBub24tZW1vdGlvbmFsIGNodW5rcw0KICANCiAgbiA8LSBucm93KGRhdGEua2VwdCkNCiAgZGF0YS5rZXB0IDwtIGRhdGEua2VwdFtjKDE6KG4tKG4lJW1heC53aW5kb3cuc2l6ZSkpKSxdDQogIA0KICBsZW5ndGgoZGF0YS5rZXB0JHBhcnRpY2lwYW50KQ0KICANCiAgDQogIHJlc3VsdHMgPC0gYygpDQogIGZvciAocHJvY2VzcyBpbiBjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcykNCiAgICB7DQogICAgcmVzdWx0cyA8LSBjKHJlc3VsdHMsIHN1bShkYXRhLmtlcHQkY29sbGFib3JhdGl2ZS5wcm9jZXNzZXM9PXByb2Nlc3MpKQ0KICAgIH0NCiAgDQogIG5vbi5mb2N1c2VkLnRhYmxlLnAyWyxwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIyIildIDwtIHJlc3VsdHMvKGxlbmd0aChkYXRhLmtlcHQkY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpJS8lbWF4LndpbmRvdy5zaXplKQ0KICByZXN1bHRzIDwtIGMoKQ0KICANCn0NCg0Kbm9uLmZvY3VzZWQudGFibGUucDINCg0KI1AwMSBwYXJ0aWNpcGFudHMNCm4gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1sZW5ndGgoY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpLG5jb2w9MCkNCm5vbi5mb2N1c2VkLnRhYmxlLnAxIDwtIGRhdGEuZnJhbWUobikNCnJvd25hbWVzKG5vbi5mb2N1c2VkLnRhYmxlLnAxKSA8LSBjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcw0KDQoNCmZvciAocCBpbiBwYXJ0aWNpcGFudHNfZWF0X2ZvY3VzZWRfUDAyKQ0Kew0KICBmb2N1c2VkLnRpbWVzIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSJmb2N1c2VkIiksYygidW5peC50aW1lLnZpZGVvIildDQogIA0KICB0by5iZS5kcm9wcGVkIDwtIHZlY3RvcigpDQogIA0KICBmb3IgKGkgaW4gc2VxKDE6bGVuZ3RoKGZvY3VzZWQudGltZXMpKSkNCiAgew0KICAgIHRvLmJlLmRyb3BwZWQgPC0gYyh0by5iZS5kcm9wcGVkLCB3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKSAmIGRhdGEkdW5peC50aW1lLnZpZGVvID4gZm9jdXNlZC50aW1lc1tpXSlbMTptYXgud2luZG93LnNpemVdKQ0KICAgIA0KICB9DQogIA0KICAjcmVtb3ZlIE5BIHdoZW4gbWF4LndpbmRvdy5zaXplIGdvZXMgb3V0IG9mIGJvdW5kcyBiZWNhdXNlIHRoZSBlbmQgb2YgY29sbGFib3JhdGl2ZSBhY3RzIGZvciB0aGF0IHBhcnRpY2lwYW50IGlzIHJlYWNoZWQNCiAgdG8uYmUuZHJvcHBlZCA8LSB0by5iZS5kcm9wcGVkWyFpcy5uYSh0by5iZS5kcm9wcGVkKV0gDQogIGRhdGEua2VwdCA8LSBkYXRhWy10by5iZS5kcm9wcGVkLF0gI2RhdGEua2VwdCBpcyB0aGUgZGF0YSB3aXRob3V0IGVtb3Rpb25hbCBjaHVua3MNCiAgDQogIGRhdGEua2VwdCA8LSBkYXRhLmtlcHRbZGF0YS5rZXB0JHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKSxdDQogIA0KICAjS2VlcCBhIG51bWJlciBvZiBsaW5lcyB0aGF0IGlzIGEgbXVsdGlwbGUgb2YgbWF4LndpbmRvd3Muc2l6ZSA9IG51bWJlciBvZiBub24tZW1vdGlvbmFsIGNodW5rcw0KICBuIDwtIG5yb3coZGF0YS5rZXB0KQ0KICBkYXRhLmtlcHQgPC0gZGF0YS5rZXB0W2MoMToobi0obiUlbWF4LndpbmRvdy5zaXplKSkpLF0NCiAgDQogIGxlbmd0aChkYXRhLmtlcHQkcGFydGljaXBhbnQpDQogIA0KICByZXN1bHRzIDwtIGMoKQ0KICBmb3IgKHByb2Nlc3MgaW4gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpDQogICAgew0KICAgIHJlc3VsdHMgPC0gYyhyZXN1bHRzLCBzdW0oZGF0YS5rZXB0JGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzPT1wcm9jZXNzKSkNCiAgICB9DQogIA0KICBub24uZm9jdXNlZC50YWJsZS5wMVsscGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMSIpXSA8LSByZXN1bHRzLyhsZW5ndGgoZGF0YS5rZXB0JGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSUvJW1heC53aW5kb3cuc2l6ZSkNCiAgcmVzdWx0cyA8LSBjKCkNCiAgDQp9DQoNCm5vbi5mb2N1c2VkLnRhYmxlLnAxDQoNCm5vbi5mb2N1c2VkLnRhYmxlIDwtIGNiaW5kKG5vbi5mb2N1c2VkLnRhYmxlLnAxLCBub24uZm9jdXNlZC50YWJsZS5wMikNCm5vbi5mb2N1c2VkLnRhYmxlDQpgYGANCg0KIyMjIERlbGlnaHRlZA0KDQpgYGB7cn0NCiNGaW5kIGNhc2VzIGF2YWlsYWJsZSBmb3IgZGVsaWdodGVkDQoNCmRlbGlnaHRlZC5jYXNlcyA8LSBjKCkNCg0KZW1vdGlvbiA9ICJkZWxpZ2h0ZWQiDQpmb3IgKHBhcnRpY2lwYW50IGluIHBhcnRpY2lwYW50c19lYXQpIHsNCiAgICBwcmludChwYXN0ZSgiUG91ciBsZSBwYXJ0aWNpcGFudCAiLCBwYXJ0aWNpcGFudCwiIGlsIHkgYSIsIGxlbmd0aChkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcGFydGljaXBhbnQgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09IGVtb3Rpb24pLGMoInNoYXJlZC5lbW90aW9uIildKSwiY29ycmVzcG9uZGFuY2UocykiKSkNCiAgICBkZWxpZ2h0ZWQuY2FzZXNbcGFydGljaXBhbnRdIDwtIGxlbmd0aChkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcGFydGljaXBhbnQgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09IGVtb3Rpb24pLGMoInNoYXJlZC5lbW90aW9uIildKQ0KfQ0KDQpkZWxpZ2h0ZWQuYXZhaWxhYmxlLmNhc2VzIDwtIGRlbGlnaHRlZC5jYXNlc1tkZWxpZ2h0ZWQuY2FzZXMgIT0gMF0NCmRlbGlnaHRlZC5hdmFpbGFibGUuY2FzZXMNCmxlbmd0aChkZWxpZ2h0ZWQuYXZhaWxhYmxlLmNhc2VzKQ0KbmFtZXMoZGVsaWdodGVkLmF2YWlsYWJsZS5jYXNlcykNCg0KYGBgDQoNCmBgYHtyfQ0KI2RlbGlnaHRlZCBzYW1wbGUNCnBhcnRpY2lwYW50c19lYXRfZGVsaWdodGVkX1AwMSA8LSBjKCJEMDJQMDEiLCJEMDVQMDEiLCJEMDlQMDEiLCJEMjZQMDEiLCJEMjdQMDEiLCJEMjlQMDEiKQ0KcGFydGljaXBhbnRzX2VhdF9kZWxpZ2h0ZWRfUDAyIDwtIGMoIkQwOVAwMiIsIkQxM1AwMiIsIkQyMVAwMiIsIkQyN1AwMiIsIkQyOVAwMiIpDQpgYGANCg0KYGBge3J9DQojQ29tcHV0ZSB0aGUgcmVhbC10aW1lIHVzZSBmb3IgdGhlIGVtb3Rpb24gZGVsaWdodGVkDQoNCiNzZWxlY3QgdGhlIHN1YnNldCBvZiBjb2xsYWJvcmF0aXZlIHByb2Nlc3NlcyBmb3IgYSBnaXZlbiBwYXJ0aWNpcGFudC4gRm9yIHRoZSBlbW90aW9uIGRlbGlnaHRlZCwgdGhlIChtYXgud2luZG93cy5zaXplKSBjb2xsYWJvcmF0aXZlIHByb2Nlc3NlcyBvZiB0aGUgb3RoZXIncyBwYXJ0bmVyIGZyb20gdGhlIHNhbWUgZHlhZCBhcmUgc2VsZWN0ZWQNCg0KI1AwMiBwYXJ0aWNpcGFudHMNCm4gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1sZW5ndGgoY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpLG5jb2w9MCkNCmRlbGlnaHRlZC50YWJsZS5wMiA8LSBkYXRhLmZyYW1lKG4pDQpyb3duYW1lcyhkZWxpZ2h0ZWQudGFibGUucDIpIDwtIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzDQoNCmZvciAocCBpbiBwYXJ0aWNpcGFudHNfZWF0X2RlbGlnaHRlZF9QMDEpDQp7DQogIG0gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1tYXgud2luZG93LnNpemUsbmNvbD0wKQ0KICBkZWxpZ2h0ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUgPC0gZGF0YS5mcmFtZShtKQ0KDQogIGRlbGlnaHRlZC50aW1lcyA8LSBkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcCAmIGRhdGEkc2hhcmVkLmVtb3Rpb24gPT0iZGVsaWdodGVkIiksYygidW5peC50aW1lLnZpZGVvIildDQogIGRlbGlnaHRlZC50aW1lcy5sZW5ndGggPC0gbGVuZ3RoKGRlbGlnaHRlZC50aW1lcykNCg0KICBmb3IgKGkgaW4gc2VxKDE6bGVuZ3RoKGRlbGlnaHRlZC50aW1lcykpKQ0KICB7DQogICAgZGVsaWdodGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlWyxwYXN0ZTAoIm9jY3VyZW5jZSIsaSldIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIyIikgJiBkYXRhJHVuaXgudGltZS52aWRlbyA+IGRlbGlnaHRlZC50aW1lc1tpXSksYygiY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMiKV1bMTptYXgud2luZG93LnNpemVdIA0KICB9DQoNCiAgZGVsaWdodGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlDQogICNjaGVjayBpZiB0aGUgZW1vdGlvbiB3aW5kb3dzIGFsbCBoYXZlIGEgbGVuZ3RoIG9mIG1heC53aW5kb3cuc2l6ZQ0KICAjd2hlbiBpdCBpcyBub3QgdGhlIGNhc2UsIHRoZSBlbW90aW9uIHdpbmRvdyBpcyByZW1vdmVkDQogIGZvciAoY29sIGluIGNvbG5hbWVzKGRlbGlnaHRlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkpew0KICAgIGlmIChhbnlOQShkZWxpZ2h0ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLGNvbF0pKSB7DQogICAgICBkZWxpZ2h0ZWQudGltZXMubGVuZ3RoIDwtIGRlbGlnaHRlZC50aW1lcy5sZW5ndGgtMQ0KICAgICAgZGVsaWdodGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlID0gZGVsaWdodGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlWywhKG5hbWVzKGRlbGlnaHRlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkgJWluJSBjKGNvbCkpXQ0KICAgIH0NCiAgfQ0KICANCiAgI2NvbXB1dGUgdGhlIHJlYWwtdGltZSB1c2UgZm9yIGV2ZXJ5IGNvbGxhYm9yYXRpdmUgcHJvY2Vzcw0KICB4IDwtIGMoKQ0KICBmb3IgKGkgaW4gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpDQogIHsNCiAgICB4W2ldIDwtIGxlbmd0aChkZWxpZ2h0ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbZGVsaWdodGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlID09IGldKQ0KICB9DQogIHggPC0geC9kZWxpZ2h0ZWQudGltZXMubGVuZ3RoICNudW1iZXIgb2YgZW1vdGlvbiB3aW5kb3dzDQogIGRlbGlnaHRlZC50YWJsZS5wMlsscGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMiIpXSA9IHgNCn0NCg0KZGVsaWdodGVkLnRhYmxlLnAyDQoNCiNQMDEgcGFydGljaXBhbnRzDQpuIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bGVuZ3RoKGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSxuY29sPTApDQpkZWxpZ2h0ZWQudGFibGUucDEgPC0gZGF0YS5mcmFtZShuKQ0Kcm93bmFtZXMoZGVsaWdodGVkLnRhYmxlLnAxKSA8LSBjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcw0KDQpmb3IgKHAgaW4gcGFydGljaXBhbnRzX2VhdF9kZWxpZ2h0ZWRfUDAyKQ0Kew0KICBtIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bWF4LndpbmRvdy5zaXplLG5jb2w9MCkNCiAgZGVsaWdodGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlIDwtIGRhdGEuZnJhbWUobSkNCg0KICBkZWxpZ2h0ZWQudGltZXMgPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHAgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09ICJkZWxpZ2h0ZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgZGVsaWdodGVkLnRpbWVzLmxlbmd0aCA8LSBsZW5ndGgoZGVsaWdodGVkLnRpbWVzKQ0KICANCiAgZm9yIChpIGluIHNlcSgxOmxlbmd0aChkZWxpZ2h0ZWQudGltZXMpKSkNCiAgew0KICAgIGRlbGlnaHRlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVsscGFzdGUwKCJvY2N1cmVuY2UiLGkpXSA8LSBkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMSIpICYgZGF0YSR1bml4LnRpbWUudmlkZW8gPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxpZ2h0ZWQudGltZXNbaV0pLGMoImNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzIildWzE6bWF4LndpbmRvdy5zaXplXSANCiAgfQ0KDQogIGRlbGlnaHRlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZQ0KICANCiAgI2NoZWNrIGlmIHRoZSBlbW90aW9uIHdpbmRvd3MgYWxsIGhhdmUgYSBsZW5ndGggb2YgbWF4LndpbmRvdy5zaXplDQogICN3aGVuIGl0IGlzIG5vdCB0aGUgY2FzZSwgdGhlIGVtb3Rpb24gd2luZG93IGlzIHJlbW92ZWQNCiAgZm9yIChjb2wgaW4gY29sbmFtZXMoZGVsaWdodGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlKSl7DQogICAgaWYgKGFueU5BKGRlbGlnaHRlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVssY29sXSkpIHsNCiAgICAgIGRlbGlnaHRlZC50aW1lcy5sZW5ndGggPC0gZGVsaWdodGVkLnRpbWVzLmxlbmd0aC0xDQogICAgICBkZWxpZ2h0ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUgPSBkZWxpZ2h0ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLCEobmFtZXMoZGVsaWdodGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlKSAlaW4lIGMoY29sKSldDQogICAgfQ0KICB9DQogIA0KICAjY29tcHV0ZSB0aGUgcmVhbC10aW1lIHVzZSBmb3IgZXZlcnkgY29sbGFib3JhdGl2ZSBwcm9jZXNzDQogIHggPC0gYygpDQogIGZvciAoaSBpbiBjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcykNCiAgew0KICAgIHhbaV0gPC0gbGVuZ3RoKGRlbGlnaHRlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVtkZWxpZ2h0ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUgPT0gaV0pDQogIH0NCiAgeCA8LSB4L2RlbGlnaHRlZC50aW1lcy5sZW5ndGggI251bWJlciBvZiBlbW90aW9uIHdpbmRvd3MNCiAgZGVsaWdodGVkLnRhYmxlLnAxWyxwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIxIildID0geA0KfQ0KDQpkZWxpZ2h0ZWQudGFibGUucDEgICAgDQoNCmRlbGlnaHRlZC50YWJsZSA8LSBjYmluZChkZWxpZ2h0ZWQudGFibGUucDEsIGRlbGlnaHRlZC50YWJsZS5wMikNCmRlbGlnaHRlZC50YWJsZQ0KYGBgDQoNCmBgYHtyfQ0KI0NvbXB1dGUgdGhlIHJlYWwtdGltZSB1c2Ugd2hlbiBubyBlbW90aW9uIGRlbGlnaHRlZA0KDQojU2VsZWN0IGEgc3Vic2V0IG9mIHRoZSBkYXRhIG5vdCBpbmNsdWRpbmcgdGhlIGVtb3Rpb25hbCBjb2xsYWJvcmF0aXZlIHByb2Nlc3NlcyB0aGF0IGFyZSBlbWl0dGVkIGp1c3QgYWZ0ZXIgdGhlIGVtb3Rpb24gb2YgaW50ZXJlc3QNCg0KI1AwMiBwYXJ0aWNpcGFudHMNCm4gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1sZW5ndGgoY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpLG5jb2w9MCkNCm5vbi5kZWxpZ2h0ZWQudGFibGUucDIgPC0gZGF0YS5mcmFtZShuKQ0Kcm93bmFtZXMobm9uLmRlbGlnaHRlZC50YWJsZS5wMikgPC0gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfZGVsaWdodGVkX1AwMSkNCnsNCiAgZGVsaWdodGVkLnRpbWVzIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSJkZWxpZ2h0ZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgDQogIHRvLmJlLmRyb3BwZWQgPC0gdmVjdG9yKCkNCiAgDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgoZGVsaWdodGVkLnRpbWVzKSkpDQogIHsNCiAgICB0by5iZS5kcm9wcGVkIDwtIGModG8uYmUuZHJvcHBlZCwgd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIyIikgJiBkYXRhJHVuaXgudGltZS52aWRlbyA+IGRlbGlnaHRlZC50aW1lc1tpXSlbMTptYXgud2luZG93LnNpemVdKQ0KICAgIA0KICB9DQogIA0KICAjcmVtb3ZlIE5BIHdoZW4gbWF4LndpbmRvdy5zaXplIGdvZXMgb3V0IG9mIGJvdW5kcyBiZWNhdXNlIHRoZSBlbmQgb2YgY29sbGFib3JhdGl2ZSBhY3RzIGZvciB0aGF0IHBhcnRpY2lwYW50IGlzIHJlYWNoZWQNCiAgdG8uYmUuZHJvcHBlZCA8LSB0by5iZS5kcm9wcGVkWyFpcy5uYSh0by5iZS5kcm9wcGVkKV0gDQogIA0KICBkYXRhLmtlcHQgPC0gZGF0YVstdG8uYmUuZHJvcHBlZCxdICNkYXRhLmtlcHQgaXMgdGhlIGRhdGEgd2l0aG91dCBlbW90aW9uYWwgY2h1bmtzDQogIA0KICBkYXRhLmtlcHQgPC0gZGF0YS5rZXB0W2RhdGEua2VwdCRwYXJ0aWNpcGFudCA9PSBwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIyIiksXQ0KICANCiAgI2tlZXAgYSBudW1iZXIgb2YgbGluZXMgdGhhdCBpcyBhIG11bHRpcGxlIG9mIG1heC53aW5kb3dzLnNpemUgPSBudW1iZXIgb2Ygbm9uLWVtb3Rpb25hbCBjaHVua3MNCiAgbiA8LSBucm93KGRhdGEua2VwdCkNCiAgZGF0YS5rZXB0IDwtIGRhdGEua2VwdFtjKDE6KG4tKG4lJW1heC53aW5kb3cuc2l6ZSkpKSxdDQogIA0KICBsZW5ndGgoZGF0YS5rZXB0JHBhcnRpY2lwYW50KQ0KICANCiAgDQogIHJlc3VsdHMgPC0gYygpDQogIGZvciAocHJvY2VzcyBpbiBjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcykNCiAgICB7DQogICAgcmVzdWx0cyA8LSBjKHJlc3VsdHMsIHN1bShkYXRhLmtlcHQkY29sbGFib3JhdGl2ZS5wcm9jZXNzZXM9PXByb2Nlc3MpKQ0KICAgIH0NCiAgDQogIG5vbi5kZWxpZ2h0ZWQudGFibGUucDJbLHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjIiKV0gPC0gcmVzdWx0cy8obGVuZ3RoKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyklLyVtYXgud2luZG93LnNpemUpDQogIHJlc3VsdHMgPC0gYygpDQogIA0KfQ0KDQpub24uZGVsaWdodGVkLnRhYmxlLnAyDQoNCiNQMDEgcGFydGljaXBhbnRzDQpuIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bGVuZ3RoKGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSxuY29sPTApDQpub24uZGVsaWdodGVkLnRhYmxlLnAxIDwtIGRhdGEuZnJhbWUobikNCnJvd25hbWVzKG5vbi5kZWxpZ2h0ZWQudGFibGUucDEpIDwtIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzDQoNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfZGVsaWdodGVkX1AwMikNCnsNCiAgZGVsaWdodGVkLnRpbWVzIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSJkZWxpZ2h0ZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgDQogIHRvLmJlLmRyb3BwZWQgPC0gdmVjdG9yKCkNCiAgDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgoZGVsaWdodGVkLnRpbWVzKSkpDQogIHsNCiAgICB0by5iZS5kcm9wcGVkIDwtIGModG8uYmUuZHJvcHBlZCwgd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIxIikgJiBkYXRhJHVuaXgudGltZS52aWRlbyA+IGRlbGlnaHRlZC50aW1lc1tpXSlbMTptYXgud2luZG93LnNpemVdKQ0KICAgIA0KICB9DQogIA0KICAjcmVtb3ZlIE5BIHdoZW4gbWF4LndpbmRvdy5zaXplIGdvZXMgb3V0IG9mIGJvdW5kcyBiZWNhdXNlIHRoZSBlbmQgb2YgY29sbGFib3JhdGl2ZSBhY3RzIGZvciB0aGF0IHBhcnRpY2lwYW50IGlzIHJlYWNoZWQNCiAgdG8uYmUuZHJvcHBlZCA8LSB0by5iZS5kcm9wcGVkWyFpcy5uYSh0by5iZS5kcm9wcGVkKV0gDQogIA0KICBkYXRhLmtlcHQgPC0gZGF0YVstdG8uYmUuZHJvcHBlZCxdICNkYXRhLmtlcHQgaXMgdGhlIGRhdGEgd2l0aG91dCBlbW90aW9uYWwgY2h1bmtzDQogIA0KICBkYXRhLmtlcHQgPC0gZGF0YS5rZXB0W2RhdGEua2VwdCRwYXJ0aWNpcGFudCA9PSBwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIxIiksXQ0KICANCiAgI2tlZXAgYSBudW1iZXIgb2YgbGluZXMgdGhhdCBpcyBhIG11bHRpcGxlIG9mIG1heC53aW5kb3dzLnNpemUgPSBudW1iZXIgb2Ygbm9uLWVtb3Rpb25hbCBjaHVua3MNCiAgbiA8LSBucm93KGRhdGEua2VwdCkNCiAgZGF0YS5rZXB0IDwtIGRhdGEua2VwdFtjKDE6KG4tKG4lJW1heC53aW5kb3cuc2l6ZSkpKSxdDQogIA0KICBsZW5ndGgoZGF0YS5rZXB0JHBhcnRpY2lwYW50KQ0KICANCiAgDQogIHJlc3VsdHMgPC0gYygpDQogIGZvciAocHJvY2VzcyBpbiBjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcykNCiAgICB7DQogICAgcmVzdWx0cyA8LSBjKHJlc3VsdHMsIHN1bShkYXRhLmtlcHQkY29sbGFib3JhdGl2ZS5wcm9jZXNzZXM9PXByb2Nlc3MpKQ0KICAgIH0NCiAgDQogIG5vbi5kZWxpZ2h0ZWQudGFibGUucDFbLHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKV0gPC0gcmVzdWx0cy8obGVuZ3RoKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyklLyVtYXgud2luZG93LnNpemUpDQogIHJlc3VsdHMgPC0gYygpDQogIA0KfQ0KDQpub24uZGVsaWdodGVkLnRhYmxlLnAxDQoNCm5vbi5kZWxpZ2h0ZWQudGFibGUgPC0gY2JpbmQobm9uLmRlbGlnaHRlZC50YWJsZS5wMSwgbm9uLmRlbGlnaHRlZC50YWJsZS5wMikNCm5vbi5kZWxpZ2h0ZWQudGFibGUNCmBgYA0KDQojIyMgU2F0aXNmaWVkDQoNCmBgYHtyfQ0KI0ZpbmQgY2FzZXMgYXZhaWxhYmxlIGZvciBzYXRpc2ZpZWQNCg0Kc2F0aXNmaWVkLmNhc2VzIDwtIGMoKQ0KDQplbW90aW9uID0gInNhdGlzZmllZCINCmZvciAocGFydGljaXBhbnQgaW4gcGFydGljaXBhbnRzX2VhdCkgew0KICAgIHByaW50KHBhc3RlKCJQb3VyIGxlIHBhcnRpY2lwYW50ICIsIHBhcnRpY2lwYW50LCIgaWwgeSBhIiwgbGVuZ3RoKGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXJ0aWNpcGFudCAmIGRhdGEkc2hhcmVkLmVtb3Rpb24gPT0gZW1vdGlvbiksYygic2hhcmVkLmVtb3Rpb24iKV0pLCJjb3JyZXNwb25kYW5jZShzKSIpKQ0KICAgIHNhdGlzZmllZC5jYXNlc1twYXJ0aWNpcGFudF0gPC0gbGVuZ3RoKGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXJ0aWNpcGFudCAmIGRhdGEkc2hhcmVkLmVtb3Rpb24gPT0gZW1vdGlvbiksYygic2hhcmVkLmVtb3Rpb24iKV0pDQp9DQoNCnNhdGlzZmllZC5hdmFpbGFibGUuY2FzZXMgPC0gc2F0aXNmaWVkLmNhc2VzW3NhdGlzZmllZC5jYXNlcyAhPSAwXQ0Kc2F0aXNmaWVkLmF2YWlsYWJsZS5jYXNlcw0KbGVuZ3RoKHNhdGlzZmllZC5hdmFpbGFibGUuY2FzZXMpDQpuYW1lcyhzYXRpc2ZpZWQuYXZhaWxhYmxlLmNhc2VzKQ0KDQpgYGANCg0KYGBge3J9DQojc2F0aXNmaWVkIHNhbXBsZQ0KcGFydGljaXBhbnRzX2VhdF9zYXRpc2ZpZWRfUDAxIDwtIGMoIkQwMlAwMSIsIkQwNVAwMSIsIkQwOVAwMSIsIkQxNlAwMSIsIkQyMVAwMSIsIkQyM1AwMSIsIkQyNlAwMSIsIkQyOVAwMSIpDQpwYXJ0aWNpcGFudHNfZWF0X3NhdGlzZmllZF9QMDIgPC0gYygiRDAyUDAyIiwiRDA5UDAyIiwiRDEzUDAyIiwiRDE2UDAyIiwiRDIxUDAyIiwiRDI2UDAyIiwiRDI3UDAyIiwiRDI5UDAyIikNCmBgYA0KDQoNCmBgYHtyfQ0KI0NvbXB1dGUgdGhlIHJlYWwtdGltZSB1c2UgZm9yIHRoZSBlbW90aW9uIHNhdGlzZmllZA0KDQojc2VsZWN0IHRoZSBzdWJzZXQgb2YgY29sbGFib3JhdGl2ZSBwcm9jZXNzZXMgZm9yIGEgZ2l2ZW4gcGFydGljaXBhbnQuIEZvciB0aGUgZW1vdGlvbiBzYXRpc2ZpZWQsIHRoZSAobWF4LndpbmRvd3Muc2l6ZSkgY29sbGFib3JhdGl2ZSBwcm9jZXNzZXMgb2YgdGhlIG90aGVyJ3MgcGFydG5lciBmcm9tIHRoZSBzYW1lIGR5YWQgYXJlIHNlbGVjdGVkDQoNCiNQMDIgcGFydGljaXBhbnRzDQpuIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bGVuZ3RoKGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSxuY29sPTApDQpzYXRpc2ZpZWQudGFibGUucDIgPC0gZGF0YS5mcmFtZShuKQ0Kcm93bmFtZXMoc2F0aXNmaWVkLnRhYmxlLnAyKSA8LSBjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcw0KDQpmb3IgKHAgaW4gcGFydGljaXBhbnRzX2VhdF9zYXRpc2ZpZWRfUDAxKQ0Kew0KICBtIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bWF4LndpbmRvdy5zaXplLG5jb2w9MCkNCiAgc2F0aXNmaWVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlIDwtIGRhdGEuZnJhbWUobSkNCg0KICBzYXRpc2ZpZWQudGltZXMgPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHAgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09InNhdGlzZmllZCIpLGMoInVuaXgudGltZS52aWRlbyIpXQ0KICBzYXRpc2ZpZWQudGltZXMubGVuZ3RoIDwtIGxlbmd0aChzYXRpc2ZpZWQudGltZXMpDQoNCiAgZm9yIChpIGluIHNlcSgxOmxlbmd0aChzYXRpc2ZpZWQudGltZXMpKSkNCiAgew0KICAgIHNhdGlzZmllZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVsscGFzdGUwKCJvY2N1cmVuY2UiLGkpXSA8LSBkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMiIpICYgZGF0YSR1bml4LnRpbWUudmlkZW8gPiBzYXRpc2ZpZWQudGltZXNbaV0pLGMoImNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzIildWzE6bWF4LndpbmRvdy5zaXplXSANCiAgfQ0KDQogIHNhdGlzZmllZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZQ0KICAjY2hlY2sgaWYgdGhlIGVtb3Rpb24gd2luZG93cyBhbGwgaGF2ZSBhIGxlbmd0aCBvZiBtYXgud2luZG93LnNpemUNCiAgI3doZW4gaXQgaXMgbm90IHRoZSBjYXNlLCB0aGUgZW1vdGlvbiB3aW5kb3cgaXMgcmVtb3ZlZA0KICBmb3IgKGNvbCBpbiBjb2xuYW1lcyhzYXRpc2ZpZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUpKXsNCiAgICBpZiAoYW55TkEoc2F0aXNmaWVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlWyxjb2xdKSkgew0KICAgICAgc2F0aXNmaWVkLnRpbWVzLmxlbmd0aCA8LSBzYXRpc2ZpZWQudGltZXMubGVuZ3RoLTENCiAgICAgIHNhdGlzZmllZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSA9IHNhdGlzZmllZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVssIShuYW1lcyhzYXRpc2ZpZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUpICVpbiUgYyhjb2wpKV0NCiAgICB9DQogIH0NCiAgDQogICNjb21wdXRlIHRoZSByZWFsLXRpbWUgdXNlIGZvciBldmVyeSBjb2xsYWJvcmF0aXZlIHByb2Nlc3MNCiAgeCA8LSBjKCkNCiAgZm9yIChpIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKQ0KICB7DQogICAgeFtpXSA8LSBsZW5ndGgoc2F0aXNmaWVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlW3NhdGlzZmllZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSA9PSBpXSkNCiAgfQ0KICB4IDwtIHgvc2F0aXNmaWVkLnRpbWVzLmxlbmd0aCAjbnVtYmVyIG9mIGVtb3Rpb24gd2luZG93cw0KICBzYXRpc2ZpZWQudGFibGUucDJbLHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjIiKV0gPSB4DQp9DQoNCnNhdGlzZmllZC50YWJsZS5wMg0KDQojUDAxIHBhcnRpY2lwYW50cw0KbiA8LSBtYXRyaXgoZGF0YT1OQSxucm93PWxlbmd0aChjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyksbmNvbD0wKQ0Kc2F0aXNmaWVkLnRhYmxlLnAxIDwtIGRhdGEuZnJhbWUobikNCnJvd25hbWVzKHNhdGlzZmllZC50YWJsZS5wMSkgPC0gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfc2F0aXNmaWVkX1AwMikNCnsNCiAgbSA8LSBtYXRyaXgoZGF0YT1OQSxucm93PW1heC53aW5kb3cuc2l6ZSxuY29sPTApDQogIHNhdGlzZmllZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSA8LSBkYXRhLmZyYW1lKG0pDQoNCiAgc2F0aXNmaWVkLnRpbWVzIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSAic2F0aXNmaWVkIiksYygidW5peC50aW1lLnZpZGVvIildDQogIHNhdGlzZmllZC50aW1lcy5sZW5ndGggPC0gbGVuZ3RoKHNhdGlzZmllZC50aW1lcykNCiAgDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgoc2F0aXNmaWVkLnRpbWVzKSkpDQogIHsNCiAgICBzYXRpc2ZpZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLHBhc3RlMCgib2NjdXJlbmNlIixpKV0gPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKSAmIGRhdGEkdW5peC50aW1lLnZpZGVvID4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F0aXNmaWVkLnRpbWVzW2ldKSxjKCJjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyIpXVsxOm1heC53aW5kb3cuc2l6ZV0gDQogIH0NCg0KICBzYXRpc2ZpZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUNCiAgDQogICNjaGVjayBpZiB0aGUgZW1vdGlvbiB3aW5kb3dzIGFsbCBoYXZlIGEgbGVuZ3RoIG9mIG1heC53aW5kb3cuc2l6ZQ0KICAjd2hlbiBpdCBpcyBub3QgdGhlIGNhc2UsIHRoZSBlbW90aW9uIHdpbmRvdyBpcyByZW1vdmVkDQogIGZvciAoY29sIGluIGNvbG5hbWVzKHNhdGlzZmllZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkpew0KICAgIGlmIChhbnlOQShzYXRpc2ZpZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLGNvbF0pKSB7DQogICAgICBzYXRpc2ZpZWQudGltZXMubGVuZ3RoIDwtIHNhdGlzZmllZC50aW1lcy5sZW5ndGgtMQ0KICAgICAgc2F0aXNmaWVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlID0gc2F0aXNmaWVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlWywhKG5hbWVzKHNhdGlzZmllZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkgJWluJSBjKGNvbCkpXQ0KICAgIH0NCiAgfQ0KICANCiAgI2NvbXB1dGUgdGhlIHJlYWwtdGltZSB1c2UgZm9yIGV2ZXJ5IGNvbGxhYm9yYXRpdmUgcHJvY2Vzcw0KICB4IDwtIGMoKQ0KICBmb3IgKGkgaW4gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpDQogIHsNCiAgICB4W2ldIDwtIGxlbmd0aChzYXRpc2ZpZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbc2F0aXNmaWVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlID09IGldKQ0KICB9DQogIHggPC0geC9zYXRpc2ZpZWQudGltZXMubGVuZ3RoICNudW1iZXIgb2YgZW1vdGlvbiB3aW5kb3dzDQogIHNhdGlzZmllZC50YWJsZS5wMVsscGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMSIpXSA9IHgNCn0NCg0Kc2F0aXNmaWVkLnRhYmxlLnAxICAgIA0KDQpzYXRpc2ZpZWQudGFibGUgPC0gY2JpbmQoc2F0aXNmaWVkLnRhYmxlLnAxLCBzYXRpc2ZpZWQudGFibGUucDIpDQpzYXRpc2ZpZWQudGFibGUNCmBgYA0KDQpgYGB7cn0NCiNDb21wdXRlIHRoZSByZWxhdGl2ZSB1c2Ugd2hlbiBubyBlbW90aW9uIHNhdGlzZmllZA0KDQojU2VsZWN0IGEgc3Vic2V0IG9mIHRoZSBkYXRhIG5vdCBpbmNsdWRpbmcgdGhlIGVtb3Rpb25hbCBjb2xsYWJvcmF0aXZlIHByb2Nlc3NlcyB0aGF0IGFyZSBlbWl0dGVkIGp1c3QgYWZ0ZXIgdGhlIGVtb3Rpb24gb2YgaW50ZXJlc3QNCg0KI3Jlc3VsdHMgZm9yIFAwMiBwYXJ0aWNpcGFudHNfZWF0DQoNCm4gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1sZW5ndGgoY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpLG5jb2w9MCkNCm5vbi5zYXRpc2ZpZWQudGFibGUucDIgPC0gZGF0YS5mcmFtZShuKQ0Kcm93bmFtZXMobm9uLnNhdGlzZmllZC50YWJsZS5wMikgPC0gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfc2F0aXNmaWVkX1AwMSkNCnsNCiAgc2F0aXNmaWVkLnRpbWVzIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSJzYXRpc2ZpZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgDQogIHRvLmJlLmRyb3BwZWQgPC0gdmVjdG9yKCkNCiAgDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgoc2F0aXNmaWVkLnRpbWVzKSkpDQogIHsNCiAgICB0by5iZS5kcm9wcGVkIDwtIGModG8uYmUuZHJvcHBlZCwgd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIyIikgJiBkYXRhJHVuaXgudGltZS52aWRlbyA+IHNhdGlzZmllZC50aW1lc1tpXSlbMTptYXgud2luZG93LnNpemVdKQ0KICAgIA0KICB9DQogIA0KICB0by5iZS5kcm9wcGVkIDwtIHRvLmJlLmRyb3BwZWRbIWlzLm5hKHRvLmJlLmRyb3BwZWQpXSAjcmVtb3ZlIE5BIHdoZW4gbWF4LndpbmRvdy5zaXplIGdvZXMgb3V0IG9mIGJvdW5kcyBiZWNhdXNlIHRoZSBlbmQgb2YgY29sbGFib3JhdGl2ZSBhY3RzIGZvciB0aGF0IHBhcnRpY2lwYW50IGlzIHJlYWNoZWQNCiAgDQogIGRhdGEua2VwdCA8LSBkYXRhWy10by5iZS5kcm9wcGVkLF0gI2RhdGEua2VwdCBpcyB0aGUgZGF0YSB3aXRob3V0IGVtb3Rpb25hbCBjaHVua3MNCiAgDQogIGRhdGEua2VwdCA8LSBkYXRhLmtlcHRbZGF0YS5rZXB0JHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjIiKSxdDQogIA0KICAjS2VlcCBhIG51bWJlciBvZiBsaW5lcyB0aGF0IGlzIGEgbXVsdGlwbGUgb2YgbWF4LndpbmRvd3Muc2l6ZSA9IG51bWJlciBvZiBub24tZW1vdGlvbmFsIGNodW5rcw0KICANCiAgbiA8LSBucm93KGRhdGEua2VwdCkNCiAgZGF0YS5rZXB0IDwtIGRhdGEua2VwdFtjKDE6KG4tKG4lJW1heC53aW5kb3cuc2l6ZSkpKSxdDQogIA0KICBsZW5ndGgoZGF0YS5rZXB0JHBhcnRpY2lwYW50KQ0KICANCiAgDQogIHJlc3VsdHMgPC0gYygpDQogIGZvciAocHJvY2VzcyBpbiBjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcykNCiAgICB7DQogICAgcmVzdWx0cyA8LSBjKHJlc3VsdHMsIHN1bShkYXRhLmtlcHQkY29sbGFib3JhdGl2ZS5wcm9jZXNzZXM9PXByb2Nlc3MpKQ0KICAgIH0NCiAgDQogIG5vbi5zYXRpc2ZpZWQudGFibGUucDJbLHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjIiKV0gPC0gcmVzdWx0cy8obGVuZ3RoKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyklLyVtYXgud2luZG93LnNpemUpDQogIHJlc3VsdHMgPC0gYygpDQogIA0KfQ0KDQpub24uc2F0aXNmaWVkLnRhYmxlLnAyDQoNCiNyZXN1bHRzIGZvciBQMDEgcGFydGljaXBhbnRzX2VhdA0KDQpuIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bGVuZ3RoKGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSxuY29sPTApDQpub24uc2F0aXNmaWVkLnRhYmxlLnAxIDwtIGRhdGEuZnJhbWUobikNCnJvd25hbWVzKG5vbi5zYXRpc2ZpZWQudGFibGUucDEpIDwtIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzDQoNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfc2F0aXNmaWVkX1AwMikNCnsNCiAgc2F0aXNmaWVkLnRpbWVzIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSJzYXRpc2ZpZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgDQogIHRvLmJlLmRyb3BwZWQgPC0gdmVjdG9yKCkNCiAgDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgoc2F0aXNmaWVkLnRpbWVzKSkpDQogIHsNCiAgICB0by5iZS5kcm9wcGVkIDwtIGModG8uYmUuZHJvcHBlZCwgd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIxIikgJiBkYXRhJHVuaXgudGltZS52aWRlbyA+IHNhdGlzZmllZC50aW1lc1tpXSlbMTptYXgud2luZG93LnNpemVdKQ0KICAgIA0KICB9DQogIA0KICB0by5iZS5kcm9wcGVkIDwtIHRvLmJlLmRyb3BwZWRbIWlzLm5hKHRvLmJlLmRyb3BwZWQpXSAjcmVtb3ZlIE5BIHdoZW4gbWF4LndpbmRvdy5zaXplIGdvZXMgb3V0IG9mIGJvdW5kcyBiZWNhdXNlIHRoZSBlbmQgb2YgY29sbGFib3JhdGl2ZSBhY3RzIGZvciB0aGF0IHBhcnRpY2lwYW50IGlzIHJlYWNoZWQNCiAgDQogIGRhdGEua2VwdCA8LSBkYXRhWy10by5iZS5kcm9wcGVkLF0gI2RhdGEua2VwdCBpcyB0aGUgZGF0YSB3aXRob3V0IGVtb3Rpb25hbCBjaHVua3MNCiAgDQogIGRhdGEua2VwdCA8LSBkYXRhLmtlcHRbZGF0YS5rZXB0JHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKSxdDQogIA0KICAjS2VlcCBhIG51bWJlciBvZiBsaW5lcyB0aGF0IGlzIGEgbXVsdGlwbGUgb2YgbWF4LndpbmRvd3Muc2l6ZSA9IG51bWJlciBvZiBub24tZW1vdGlvbmFsIGNodW5rcw0KICANCiAgbiA8LSBucm93KGRhdGEua2VwdCkNCiAgZGF0YS5rZXB0IDwtIGRhdGEua2VwdFtjKDE6KG4tKG4lJW1heC53aW5kb3cuc2l6ZSkpKSxdDQogIA0KICBsZW5ndGgoZGF0YS5rZXB0JHBhcnRpY2lwYW50KQ0KICANCiAgDQogIHJlc3VsdHMgPC0gYygpDQogIGZvciAocHJvY2VzcyBpbiBjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcykNCiAgICB7DQogICAgcmVzdWx0cyA8LSBjKHJlc3VsdHMsIHN1bShkYXRhLmtlcHQkY29sbGFib3JhdGl2ZS5wcm9jZXNzZXM9PXByb2Nlc3MpKQ0KICAgIH0NCiAgDQogIG5vbi5zYXRpc2ZpZWQudGFibGUucDFbLHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKV0gPC0gcmVzdWx0cy8obGVuZ3RoKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyklLyVtYXgud2luZG93LnNpemUpDQogIHJlc3VsdHMgPC0gYygpDQogIA0KfQ0KDQpub24uc2F0aXNmaWVkLnRhYmxlLnAxDQoNCm5vbi5zYXRpc2ZpZWQudGFibGUgPC0gY2JpbmQobm9uLnNhdGlzZmllZC50YWJsZS5wMSwgbm9uLnNhdGlzZmllZC50YWJsZS5wMikNCm5vbi5zYXRpc2ZpZWQudGFibGUNCmBgYA0KDQojIyMgQW11c2VkDQoNCmBgYHtyfQ0KI0ZpbmQgY2FzZXMgYXZhaWxhYmxlIGZvciBhbXVzZWQNCg0KYW11c2VkLmNhc2VzIDwtIGMoKQ0KDQplbW90aW9uID0gImFtdXNlZCINCmZvciAocGFydGljaXBhbnQgaW4gcGFydGljaXBhbnRzX2VhdCkgew0KICAgIHByaW50KHBhc3RlKCJQb3VyIGxlIHBhcnRpY2lwYW50ICIsIHBhcnRpY2lwYW50LCIgaWwgeSBhIiwgbGVuZ3RoKGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXJ0aWNpcGFudCAmIGRhdGEkc2hhcmVkLmVtb3Rpb24gPT0gZW1vdGlvbiksYygic2hhcmVkLmVtb3Rpb24iKV0pLCJjb3JyZXNwb25kYW5jZShzKSIpKQ0KICAgIGFtdXNlZC5jYXNlc1twYXJ0aWNpcGFudF0gPC0gbGVuZ3RoKGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXJ0aWNpcGFudCAmIGRhdGEkc2hhcmVkLmVtb3Rpb24gPT0gZW1vdGlvbiksYygic2hhcmVkLmVtb3Rpb24iKV0pDQp9DQoNCmFtdXNlZC5hdmFpbGFibGUuY2FzZXMgPC0gYW11c2VkLmNhc2VzW2FtdXNlZC5jYXNlcyAhPSAwXQ0KYW11c2VkLmF2YWlsYWJsZS5jYXNlcw0KbGVuZ3RoKGFtdXNlZC5hdmFpbGFibGUuY2FzZXMpDQpuYW1lcyhhbXVzZWQuYXZhaWxhYmxlLmNhc2VzKQ0KDQpgYGANCmBgYHtyfQ0KI2FtdXNlZCBzYW1wbGUNCnBhcnRpY2lwYW50c19lYXRfYW11c2VkX1AwMSA8LSBjKCJEMDJQMDEiLCJEMDVQMDEiLCJEMDdQMDEiLCJEMDlQMDEiLCJEMTNQMDEiLCJEMTZQMDEiLCJEMjFQMDEiLCJEMjNQMDEiLCJEMjZQMDEiLCJEMjdQMDEiLCJEMjlQMDEiKQ0KcGFydGljaXBhbnRzX2VhdF9hbXVzZWRfUDAyIDwtIGMoIkQwN1AwMiIsIkQwOVAwMiIsIkQxM1AwMiIsIkQyMVAwMiIsIkQyM1AwMiIsIkQyNlAwMiIsIkQyN1AwMiIpDQpgYGANCg0KYGBge3J9DQojQ29tcHV0ZSB0aGUgcmVhbC10aW1lIHVzZSBmb3IgdGhlIGVtb3Rpb24gYW11c2VkDQoNCiNzZWxlY3QgdGhlIHN1YnNldCBvZiBjb2xsYWJvcmF0aXZlIHByb2Nlc3NlcyBmb3IgYSBnaXZlbiBwYXJ0aWNpcGFudC4gRm9yIHRoZSBlbW90aW9uIGFtdXNlZCwgdGhlIChtYXgud2luZG93cy5zaXplKSBjb2xsYWJvcmF0aXZlIHByb2Nlc3NlcyBvZiB0aGUgb3RoZXIncyBwYXJ0bmVyIGZyb20gdGhlIHNhbWUgZHlhZCBhcmUgc2VsZWN0ZWQNCg0KI1AwMiBwYXJ0aWNpcGFudHMNCm4gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1sZW5ndGgoY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpLG5jb2w9MCkNCmFtdXNlZC50YWJsZS5wMiA8LSBkYXRhLmZyYW1lKG4pDQpyb3duYW1lcyhhbXVzZWQudGFibGUucDIpIDwtIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzDQoNCmZvciAocCBpbiBwYXJ0aWNpcGFudHNfZWF0X2FtdXNlZF9QMDEpDQp7DQogIG0gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1tYXgud2luZG93LnNpemUsbmNvbD0wKQ0KICBhbXVzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUgPC0gZGF0YS5mcmFtZShtKQ0KDQogIGFtdXNlZC50aW1lcyA8LSBkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcCAmIGRhdGEkc2hhcmVkLmVtb3Rpb24gPT0iYW11c2VkIiksYygidW5peC50aW1lLnZpZGVvIildDQogIGFtdXNlZC50aW1lcy5sZW5ndGggPC0gbGVuZ3RoKGFtdXNlZC50aW1lcykNCg0KICBmb3IgKGkgaW4gc2VxKDE6bGVuZ3RoKGFtdXNlZC50aW1lcykpKQ0KICB7DQogICAgYW11c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlWyxwYXN0ZTAoIm9jY3VyZW5jZSIsaSldIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIyIikgJiBkYXRhJHVuaXgudGltZS52aWRlbyA+IGFtdXNlZC50aW1lc1tpXSksYygiY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMiKV1bMTptYXgud2luZG93LnNpemVdIA0KICB9DQoNCiAgYW11c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlDQogICNjaGVjayBpZiB0aGUgZW1vdGlvbiB3aW5kb3dzIGFsbCBoYXZlIGEgbGVuZ3RoIG9mIG1heC53aW5kb3cuc2l6ZQ0KICAjd2hlbiBpdCBpcyBub3QgdGhlIGNhc2UsIHRoZSBlbW90aW9uIHdpbmRvdyBpcyByZW1vdmVkDQogIGZvciAoY29sIGluIGNvbG5hbWVzKGFtdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkpew0KICAgIGlmIChhbnlOQShhbXVzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLGNvbF0pKSB7DQogICAgICBhbXVzZWQudGltZXMubGVuZ3RoIDwtIGFtdXNlZC50aW1lcy5sZW5ndGgtMQ0KICAgICAgYW11c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlID0gYW11c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlWywhKG5hbWVzKGFtdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkgJWluJSBjKGNvbCkpXQ0KICAgIH0NCiAgfQ0KICANCiAgI2NvbXB1dGUgdGhlIHJlYWwtdGltZSB1c2UgZm9yIGV2ZXJ5IGNvbGxhYm9yYXRpdmUgcHJvY2Vzcw0KICB4IDwtIGMoKQ0KICBmb3IgKGkgaW4gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpDQogIHsNCiAgICB4W2ldIDwtIGxlbmd0aChhbXVzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbYW11c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlID09IGldKQ0KICB9DQogIHggPC0geC9hbXVzZWQudGltZXMubGVuZ3RoICNudW1iZXIgb2YgZW1vdGlvbiB3aW5kb3dzDQogIGFtdXNlZC50YWJsZS5wMlsscGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMiIpXSA9IHgNCn0NCg0KYW11c2VkLnRhYmxlLnAyDQoNCiNQMDEgcGFydGljaXBhbnRzDQpuIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bGVuZ3RoKGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSxuY29sPTApDQphbXVzZWQudGFibGUucDEgPC0gZGF0YS5mcmFtZShuKQ0Kcm93bmFtZXMoYW11c2VkLnRhYmxlLnAxKSA8LSBjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcw0KDQpmb3IgKHAgaW4gcGFydGljaXBhbnRzX2VhdF9hbXVzZWRfUDAyKQ0Kew0KICBtIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bWF4LndpbmRvdy5zaXplLG5jb2w9MCkNCiAgYW11c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlIDwtIGRhdGEuZnJhbWUobSkNCg0KICBhbXVzZWQudGltZXMgPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHAgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09ICJhbXVzZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgYW11c2VkLnRpbWVzLmxlbmd0aCA8LSBsZW5ndGgoYW11c2VkLnRpbWVzKQ0KICANCiAgZm9yIChpIGluIHNlcSgxOmxlbmd0aChhbXVzZWQudGltZXMpKSkNCiAgew0KICAgIGFtdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVsscGFzdGUwKCJvY2N1cmVuY2UiLGkpXSA8LSBkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMSIpICYgZGF0YSR1bml4LnRpbWUudmlkZW8gPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbXVzZWQudGltZXNbaV0pLGMoImNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzIildWzE6bWF4LndpbmRvdy5zaXplXSANCiAgfQ0KDQogIGFtdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZQ0KICANCiAgI2NoZWNrIGlmIHRoZSBlbW90aW9uIHdpbmRvd3MgYWxsIGhhdmUgYSBsZW5ndGggb2YgbWF4LndpbmRvdy5zaXplDQogICN3aGVuIGl0IGlzIG5vdCB0aGUgY2FzZSwgdGhlIGVtb3Rpb24gd2luZG93IGlzIHJlbW92ZWQNCiAgZm9yIChjb2wgaW4gY29sbmFtZXMoYW11c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlKSl7DQogICAgaWYgKGFueU5BKGFtdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVssY29sXSkpIHsNCiAgICAgIGFtdXNlZC50aW1lcy5sZW5ndGggPC0gYW11c2VkLnRpbWVzLmxlbmd0aC0xDQogICAgICBhbXVzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUgPSBhbXVzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLCEobmFtZXMoYW11c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlKSAlaW4lIGMoY29sKSldDQogICAgfQ0KICB9DQogIA0KICAjY29tcHV0ZSB0aGUgcmVhbC10aW1lIHVzZSBmb3IgZXZlcnkgY29sbGFib3JhdGl2ZSBwcm9jZXNzDQogIHggPC0gYygpDQogIGZvciAoaSBpbiBjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcykNCiAgew0KICAgIHhbaV0gPC0gbGVuZ3RoKGFtdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVthbXVzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUgPT0gaV0pDQogIH0NCiAgeCA8LSB4L2FtdXNlZC50aW1lcy5sZW5ndGggI251bWJlciBvZiBlbW90aW9uIHdpbmRvd3MNCiAgYW11c2VkLnRhYmxlLnAxWyxwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIxIildID0geA0KfQ0KDQphbXVzZWQudGFibGUucDEgICAgDQoNCmFtdXNlZC50YWJsZSA8LSBjYmluZChhbXVzZWQudGFibGUucDEsIGFtdXNlZC50YWJsZS5wMikNCmFtdXNlZC50YWJsZQ0KYGBgDQoNCmBgYHtyfQ0KI0NvbXB1dGUgdGhlIHJlbGF0aXZlIHVzZSB3aGVuIG5vIGVtb3Rpb24gYW11c2VkDQoNCiNTZWxlY3QgYSBzdWJzZXQgb2YgdGhlIGRhdGEgbm90IGluY2x1ZGluZyB0aGUgZW1vdGlvbmFsIGNvbGxhYm9yYXRpdmUgcHJvY2Vzc2VzIHRoYXQgYXJlIGVtaXR0ZWQganVzdCBhZnRlciB0aGUgZW1vdGlvbiBvZiBpbnRlcmVzdA0KDQojcmVzdWx0cyBmb3IgUDAyIHBhcnRpY2lwYW50c19lYXQNCg0KbiA8LSBtYXRyaXgoZGF0YT1OQSxucm93PWxlbmd0aChjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyksbmNvbD0wKQ0Kbm9uLmFtdXNlZC50YWJsZS5wMiA8LSBkYXRhLmZyYW1lKG4pDQpyb3duYW1lcyhub24uYW11c2VkLnRhYmxlLnAyKSA8LSBjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcw0KDQpmb3IgKHAgaW4gcGFydGljaXBhbnRzX2VhdF9hbXVzZWRfUDAxKQ0Kew0KICBhbXVzZWQudGltZXMgPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHAgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09ImFtdXNlZCIpLGMoInVuaXgudGltZS52aWRlbyIpXQ0KICANCiAgdG8uYmUuZHJvcHBlZCA8LSB2ZWN0b3IoKQ0KICANCiAgZm9yIChpIGluIHNlcSgxOmxlbmd0aChhbXVzZWQudGltZXMpKSkNCiAgew0KICAgIHRvLmJlLmRyb3BwZWQgPC0gYyh0by5iZS5kcm9wcGVkLCB3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjIiKSAmIGRhdGEkdW5peC50aW1lLnZpZGVvID4gYW11c2VkLnRpbWVzW2ldKVsxOm1heC53aW5kb3cuc2l6ZV0pDQogICAgDQogIH0NCiAgDQogIHRvLmJlLmRyb3BwZWQgPC0gdG8uYmUuZHJvcHBlZFshaXMubmEodG8uYmUuZHJvcHBlZCldICNyZW1vdmUgTkEgd2hlbiBtYXgud2luZG93LnNpemUgZ29lcyBvdXQgb2YgYm91bmRzIGJlY2F1c2UgdGhlIGVuZCBvZiBjb2xsYWJvcmF0aXZlIGFjdHMgZm9yIHRoYXQgcGFydGljaXBhbnQgaXMgcmVhY2hlZA0KICANCiAgZGF0YS5rZXB0IDwtIGRhdGFbLXRvLmJlLmRyb3BwZWQsXSAjZGF0YS5rZXB0IGlzIHRoZSBkYXRhIHdpdGhvdXQgZW1vdGlvbmFsIGNodW5rcw0KICANCiAgZGF0YS5rZXB0IDwtIGRhdGEua2VwdFtkYXRhLmtlcHQkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMiIpLF0NCiAgDQogICNLZWVwIGEgbnVtYmVyIG9mIGxpbmVzIHRoYXQgaXMgYSBtdWx0aXBsZSBvZiBtYXgud2luZG93cy5zaXplID0gbnVtYmVyIG9mIG5vbi1lbW90aW9uYWwgY2h1bmtzDQogIA0KICBuIDwtIG5yb3coZGF0YS5rZXB0KQ0KICBkYXRhLmtlcHQgPC0gZGF0YS5rZXB0W2MoMToobi0obiUlbWF4LndpbmRvdy5zaXplKSkpLF0NCiAgDQogIGxlbmd0aChkYXRhLmtlcHQkcGFydGljaXBhbnQpDQogIA0KICANCiAgcmVzdWx0cyA8LSBjKCkNCiAgZm9yIChwcm9jZXNzIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKQ0KICAgIHsNCiAgICByZXN1bHRzIDwtIGMocmVzdWx0cywgc3VtKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcz09cHJvY2VzcykpDQogICAgfQ0KICANCiAgbm9uLmFtdXNlZC50YWJsZS5wMlsscGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMiIpXSA8LSByZXN1bHRzLyhsZW5ndGgoZGF0YS5rZXB0JGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSUvJW1heC53aW5kb3cuc2l6ZSkNCiAgcmVzdWx0cyA8LSBjKCkNCiAgDQp9DQoNCm5vbi5hbXVzZWQudGFibGUucDINCg0KI3Jlc3VsdHMgZm9yIFAwMSBwYXJ0aWNpcGFudHNfZWF0DQoNCm4gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1sZW5ndGgoY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpLG5jb2w9MCkNCm5vbi5hbXVzZWQudGFibGUucDEgPC0gZGF0YS5mcmFtZShuKQ0Kcm93bmFtZXMobm9uLmFtdXNlZC50YWJsZS5wMSkgPC0gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMNCg0KDQpmb3IgKHAgaW4gcGFydGljaXBhbnRzX2VhdF9hbXVzZWRfUDAyKQ0Kew0KICBhbXVzZWQudGltZXMgPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHAgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09ImFtdXNlZCIpLGMoInVuaXgudGltZS52aWRlbyIpXQ0KICANCiAgdG8uYmUuZHJvcHBlZCA8LSB2ZWN0b3IoKQ0KICANCiAgZm9yIChpIGluIHNlcSgxOmxlbmd0aChhbXVzZWQudGltZXMpKSkNCiAgew0KICAgIHRvLmJlLmRyb3BwZWQgPC0gYyh0by5iZS5kcm9wcGVkLCB3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKSAmIGRhdGEkdW5peC50aW1lLnZpZGVvID4gYW11c2VkLnRpbWVzW2ldKVsxOm1heC53aW5kb3cuc2l6ZV0pDQogICAgDQogIH0NCiAgDQogIHRvLmJlLmRyb3BwZWQgPC0gdG8uYmUuZHJvcHBlZFshaXMubmEodG8uYmUuZHJvcHBlZCldICNyZW1vdmUgTkEgd2hlbiBtYXgud2luZG93LnNpemUgZ29lcyBvdXQgb2YgYm91bmRzIGJlY2F1c2UgdGhlIGVuZCBvZiBjb2xsYWJvcmF0aXZlIGFjdHMgZm9yIHRoYXQgcGFydGljaXBhbnQgaXMgcmVhY2hlZA0KICANCiAgZGF0YS5rZXB0IDwtIGRhdGFbLXRvLmJlLmRyb3BwZWQsXSAjZGF0YS5rZXB0IGlzIHRoZSBkYXRhIHdpdGhvdXQgZW1vdGlvbmFsIGNodW5rcw0KICANCiAgZGF0YS5rZXB0IDwtIGRhdGEua2VwdFtkYXRhLmtlcHQkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMSIpLF0NCiAgDQogICNLZWVwIGEgbnVtYmVyIG9mIGxpbmVzIHRoYXQgaXMgYSBtdWx0aXBsZSBvZiBtYXgud2luZG93cy5zaXplID0gbnVtYmVyIG9mIG5vbi1lbW90aW9uYWwgY2h1bmtzDQogIA0KICBuIDwtIG5yb3coZGF0YS5rZXB0KQ0KICBkYXRhLmtlcHQgPC0gZGF0YS5rZXB0W2MoMToobi0obiUlbWF4LndpbmRvdy5zaXplKSkpLF0NCiAgDQogIGxlbmd0aChkYXRhLmtlcHQkcGFydGljaXBhbnQpDQogIA0KICANCiAgcmVzdWx0cyA8LSBjKCkNCiAgZm9yIChwcm9jZXNzIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKQ0KICAgIHsNCiAgICByZXN1bHRzIDwtIGMocmVzdWx0cywgc3VtKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcz09cHJvY2VzcykpDQogICAgfQ0KICANCiAgbm9uLmFtdXNlZC50YWJsZS5wMVsscGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMSIpXSA8LSByZXN1bHRzLyhsZW5ndGgoZGF0YS5rZXB0JGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSUvJW1heC53aW5kb3cuc2l6ZSkNCiAgcmVzdWx0cyA8LSBjKCkNCiAgDQp9DQoNCm5vbi5hbXVzZWQudGFibGUucDENCg0Kbm9uLmFtdXNlZC50YWJsZSA8LSBjYmluZChub24uYW11c2VkLnRhYmxlLnAxLCBub24uYW11c2VkLnRhYmxlLnAyKQ0Kbm9uLmFtdXNlZC50YWJsZQ0KYGBgDQoNCiMjIyBSZWxheGVkDQoNCmBgYHtyfQ0KI0ZpbmQgY2FzZXMgYXZhaWxhYmxlIGZvciByZWxheGVkLCBpLmUuLCB0aGUgcGFydGljaXBhbnRzIGZvciB3aGljaCBvbmUgb3IgbW9yZSBzaGFyaW5nIG9mIHJlbGF4ZWQgb2NjdXJlZA0KDQpyZWxheGVkLmNhc2VzIDwtIGMoKQ0KDQplbW90aW9uID0gInJlbGF4ZWQiDQpmb3IgKHBhcnRpY2lwYW50IGluIHBhcnRpY2lwYW50c19lYXQpIHsNCiAgICBwcmludChwYXN0ZSgiUG91ciBsZSBwYXJ0aWNpcGFudCAiLCBwYXJ0aWNpcGFudCwiIGlsIHkgYSIsIGxlbmd0aChkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcGFydGljaXBhbnQgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09IGVtb3Rpb24pLGMoInNoYXJlZC5lbW90aW9uIildKSwiY29ycmVzcG9uZGFuY2UocykiKSkNCiAgICByZWxheGVkLmNhc2VzW3BhcnRpY2lwYW50XSA8LSBsZW5ndGgoZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhcnRpY2lwYW50ICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSBlbW90aW9uKSxjKCJzaGFyZWQuZW1vdGlvbiIpXSkNCn0NCg0KcmVsYXhlZC5hdmFpbGFibGUuY2FzZXMgPC0gcmVsYXhlZC5jYXNlc1tyZWxheGVkLmNhc2VzICE9IDBdDQpyZWxheGVkLmF2YWlsYWJsZS5jYXNlcw0KbGVuZ3RoKHJlbGF4ZWQuYXZhaWxhYmxlLmNhc2VzKQ0KbmFtZXMocmVsYXhlZC5hdmFpbGFibGUuY2FzZXMpDQoNCmBgYA0KDQpgYGB7cn0NCiNyZWxheGVkIHNhbXBsZQ0KcGFydGljaXBhbnRzX2VhdF9yZWxheGVkX1AwMSA8LSBjKCJEMDVQMDEiLCJEMDdQMDEiLCJEMDlQMDEiLCJEMjFQMDEiLCJEMjNQMDEiLCJEMjdQMDEiKQ0KcGFydGljaXBhbnRzX2VhdF9yZWxheGVkX1AwMiA8LSBjKCJEMDVQMDIiLCJEMDlQMDIiLCJEMTZQMDIiLCJEMjFQMDIiLCJEMjZQMDIiLCJEMjdQMDIiKQ0KYGBgDQoNCmBgYHtyfQ0KI0NvbXB1dGUgdGhlIHJlYWwtdGltZSB1c2UgZm9yIHRoZSBlbW90aW9uIHJlbGF4ZWQNCg0KI3NlbGVjdCB0aGUgc3Vic2V0IG9mIGNvbGxhYm9yYXRpdmUgcHJvY2Vzc2VzIGZvciBhIGdpdmVuIHBhcnRpY2lwYW50LiBGb3IgdGhlIGVtb3Rpb24gcmVsYXhlZCwgdGhlIChtYXgud2luZG93cy5zaXplKSBjb2xsYWJvcmF0aXZlIHByb2Nlc3NlcyBvZiB0aGUgb3RoZXIncyBwYXJ0bmVyIGZyb20gdGhlIHNhbWUgZHlhZCBhcmUgc2VsZWN0ZWQNCg0KI1AwMiBwYXJ0aWNpcGFudHMNCm4gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1sZW5ndGgoY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpLG5jb2w9MCkNCnJlbGF4ZWQudGFibGUucDIgPC0gZGF0YS5mcmFtZShuKQ0Kcm93bmFtZXMocmVsYXhlZC50YWJsZS5wMikgPC0gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfcmVsYXhlZF9QMDEpDQp7DQogIG0gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1tYXgud2luZG93LnNpemUsbmNvbD0wKQ0KICByZWxheGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlIDwtIGRhdGEuZnJhbWUobSkNCg0KICByZWxheGVkLnRpbWVzIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSJyZWxheGVkIiksYygidW5peC50aW1lLnZpZGVvIildDQogIHJlbGF4ZWQudGltZXMubGVuZ3RoIDwtIGxlbmd0aChyZWxheGVkLnRpbWVzKQ0KDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgocmVsYXhlZC50aW1lcykpKQ0KICB7DQogICAgcmVsYXhlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVsscGFzdGUwKCJvY2N1cmVuY2UiLGkpXSA8LSBkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMiIpICYgZGF0YSR1bml4LnRpbWUudmlkZW8gPiByZWxheGVkLnRpbWVzW2ldKSxjKCJjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyIpXVsxOm1heC53aW5kb3cuc2l6ZV0gDQogIH0NCg0KICByZWxheGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlDQogICNjaGVjayBpZiB0aGUgZW1vdGlvbiB3aW5kb3dzIGFsbCBoYXZlIGEgbGVuZ3RoIG9mIG1heC53aW5kb3cuc2l6ZQ0KICAjd2hlbiBpdCBpcyBub3QgdGhlIGNhc2UsIHRoZSBlbW90aW9uIHdpbmRvdyBpcyByZW1vdmVkDQogIGZvciAoY29sIGluIGNvbG5hbWVzKHJlbGF4ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUpKXsNCiAgICBpZiAoYW55TkEocmVsYXhlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVssY29sXSkpIHsNCiAgICAgIHJlbGF4ZWQudGltZXMubGVuZ3RoIDwtIHJlbGF4ZWQudGltZXMubGVuZ3RoLTENCiAgICAgIHJlbGF4ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUgPSByZWxheGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlWywhKG5hbWVzKHJlbGF4ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUpICVpbiUgYyhjb2wpKV0NCiAgICB9DQogIH0NCiAgDQogICNjb21wdXRlIHRoZSByZWFsLXRpbWUgdXNlIGZvciBldmVyeSBjb2xsYWJvcmF0aXZlIHByb2Nlc3MNCiAgeCA8LSBjKCkNCiAgZm9yIChpIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKQ0KICB7DQogICAgeFtpXSA8LSBsZW5ndGgocmVsYXhlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVtyZWxheGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlID09IGldKQ0KICB9DQogIHggPC0geC9yZWxheGVkLnRpbWVzLmxlbmd0aCAjbnVtYmVyIG9mIGVtb3Rpb24gd2luZG93cw0KICByZWxheGVkLnRhYmxlLnAyWyxwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIyIildID0geA0KfQ0KDQpyZWxheGVkLnRhYmxlLnAyDQoNCiNQMDEgcGFydGljaXBhbnRzDQpuIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bGVuZ3RoKGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSxuY29sPTApDQpyZWxheGVkLnRhYmxlLnAxIDwtIGRhdGEuZnJhbWUobikNCnJvd25hbWVzKHJlbGF4ZWQudGFibGUucDEpIDwtIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzDQoNCmZvciAocCBpbiBwYXJ0aWNpcGFudHNfZWF0X3JlbGF4ZWRfUDAyKQ0Kew0KICBtIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bWF4LndpbmRvdy5zaXplLG5jb2w9MCkNCiAgcmVsYXhlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSA8LSBkYXRhLmZyYW1lKG0pDQoNCiAgcmVsYXhlZC50aW1lcyA8LSBkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcCAmIGRhdGEkc2hhcmVkLmVtb3Rpb24gPT0gInJlbGF4ZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgcmVsYXhlZC50aW1lcy5sZW5ndGggPC0gbGVuZ3RoKHJlbGF4ZWQudGltZXMpDQogIA0KICBmb3IgKGkgaW4gc2VxKDE6bGVuZ3RoKHJlbGF4ZWQudGltZXMpKSkNCiAgew0KICAgIHJlbGF4ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLHBhc3RlMCgib2NjdXJlbmNlIixpKV0gPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKSAmIGRhdGEkdW5peC50aW1lLnZpZGVvID4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVsYXhlZC50aW1lc1tpXSksYygiY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMiKV1bMTptYXgud2luZG93LnNpemVdIA0KICB9DQoNCiAgcmVsYXhlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZQ0KICANCiAgI2NoZWNrIGlmIHRoZSBlbW90aW9uIHdpbmRvd3MgYWxsIGhhdmUgYSBsZW5ndGggb2YgbWF4LndpbmRvdy5zaXplDQogICN3aGVuIGl0IGlzIG5vdCB0aGUgY2FzZSwgdGhlIGVtb3Rpb24gd2luZG93IGlzIHJlbW92ZWQNCiAgZm9yIChjb2wgaW4gY29sbmFtZXMocmVsYXhlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkpew0KICAgIGlmIChhbnlOQShyZWxheGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlWyxjb2xdKSkgew0KICAgICAgcmVsYXhlZC50aW1lcy5sZW5ndGggPC0gcmVsYXhlZC50aW1lcy5sZW5ndGgtMQ0KICAgICAgcmVsYXhlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSA9IHJlbGF4ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLCEobmFtZXMocmVsYXhlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkgJWluJSBjKGNvbCkpXQ0KICAgIH0NCiAgfQ0KICANCiAgI2NvbXB1dGUgdGhlIHJlYWwtdGltZSB1c2UgZm9yIGV2ZXJ5IGNvbGxhYm9yYXRpdmUgcHJvY2Vzcw0KICB4IDwtIGMoKQ0KICBmb3IgKGkgaW4gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpDQogIHsNCiAgICB4W2ldIDwtIGxlbmd0aChyZWxheGVkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlW3JlbGF4ZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUgPT0gaV0pDQogIH0NCiAgeCA8LSB4L3JlbGF4ZWQudGltZXMubGVuZ3RoICNudW1iZXIgb2YgZW1vdGlvbiB3aW5kb3dzDQogIHJlbGF4ZWQudGFibGUucDFbLHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKV0gPSB4DQp9DQoNCnJlbGF4ZWQudGFibGUucDEgICAgDQoNCnJlbGF4ZWQudGFibGUgPC0gY2JpbmQocmVsYXhlZC50YWJsZS5wMSwgcmVsYXhlZC50YWJsZS5wMikNCnJlbGF4ZWQudGFibGUNCmBgYA0KDQpgYGB7cn0NCiNDb21wdXRlIHRoZSByZWxhdGl2ZSB1c2Ugd2hlbiBubyBlbW90aW9uIHJlbGF4ZWQNCg0KI1NlbGVjdCBhIHN1YnNldCBvZiB0aGUgZGF0YSBub3QgaW5jbHVkaW5nIHRoZSBlbW90aW9uYWwgY29sbGFib3JhdGl2ZSBwcm9jZXNzZXMgdGhhdCBhcmUgZW1pdHRlZCBqdXN0IGFmdGVyIHRoZSBlbW90aW9uIG9mIGludGVyZXN0DQoNCiNyZXN1bHRzIGZvciBQMDIgcGFydGljaXBhbnRzX2VhdA0KDQpuIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bGVuZ3RoKGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSxuY29sPTApDQpub24ucmVsYXhlZC50YWJsZS5wMiA8LSBkYXRhLmZyYW1lKG4pDQpyb3duYW1lcyhub24ucmVsYXhlZC50YWJsZS5wMikgPC0gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfcmVsYXhlZF9QMDEpDQp7DQogIHJlbGF4ZWQudGltZXMgPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHAgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09InJlbGF4ZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgDQogIHRvLmJlLmRyb3BwZWQgPC0gdmVjdG9yKCkNCiAgDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgocmVsYXhlZC50aW1lcykpKQ0KICB7DQogICAgdG8uYmUuZHJvcHBlZCA8LSBjKHRvLmJlLmRyb3BwZWQsIHdoaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMiIpICYgZGF0YSR1bml4LnRpbWUudmlkZW8gPiByZWxheGVkLnRpbWVzW2ldKVsxOm1heC53aW5kb3cuc2l6ZV0pDQogICAgDQogIH0NCiAgDQogIHRvLmJlLmRyb3BwZWQgPC0gdG8uYmUuZHJvcHBlZFshaXMubmEodG8uYmUuZHJvcHBlZCldICNyZW1vdmUgTkEgd2hlbiBtYXgud2luZG93LnNpemUgZ29lcyBvdXQgb2YgYm91bmRzIGJlY2F1c2UgdGhlIGVuZCBvZiBjb2xsYWJvcmF0aXZlIGFjdHMgZm9yIHRoYXQgcGFydGljaXBhbnQgaXMgcmVhY2hlZA0KICANCiAgZGF0YS5rZXB0IDwtIGRhdGFbLXRvLmJlLmRyb3BwZWQsXSAjZGF0YS5rZXB0IGlzIHRoZSBkYXRhIHdpdGhvdXQgZW1vdGlvbmFsIGNodW5rcw0KICANCiAgZGF0YS5rZXB0IDwtIGRhdGEua2VwdFtkYXRhLmtlcHQkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMiIpLF0NCiAgDQogICNLZWVwIGEgbnVtYmVyIG9mIGxpbmVzIHRoYXQgaXMgYSBtdWx0aXBsZSBvZiBtYXgud2luZG93cy5zaXplID0gbnVtYmVyIG9mIG5vbi1lbW90aW9uYWwgY2h1bmtzDQogIA0KICBuIDwtIG5yb3coZGF0YS5rZXB0KQ0KICBkYXRhLmtlcHQgPC0gZGF0YS5rZXB0W2MoMToobi0obiUlbWF4LndpbmRvdy5zaXplKSkpLF0NCiAgDQogIGxlbmd0aChkYXRhLmtlcHQkcGFydGljaXBhbnQpDQogIA0KICANCiAgcmVzdWx0cyA8LSBjKCkNCiAgZm9yIChwcm9jZXNzIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKQ0KICAgIHsNCiAgICByZXN1bHRzIDwtIGMocmVzdWx0cywgc3VtKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcz09cHJvY2VzcykpDQogICAgfQ0KICANCiAgbm9uLnJlbGF4ZWQudGFibGUucDJbLHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjIiKV0gPC0gcmVzdWx0cy8obGVuZ3RoKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyklLyVtYXgud2luZG93LnNpemUpDQogIHJlc3VsdHMgPC0gYygpDQogIA0KfQ0KDQpub24ucmVsYXhlZC50YWJsZS5wMg0KDQojcmVzdWx0cyBmb3IgUDAxIHBhcnRpY2lwYW50c19lYXQNCg0KbiA8LSBtYXRyaXgoZGF0YT1OQSxucm93PWxlbmd0aChjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyksbmNvbD0wKQ0Kbm9uLnJlbGF4ZWQudGFibGUucDEgPC0gZGF0YS5mcmFtZShuKQ0Kcm93bmFtZXMobm9uLnJlbGF4ZWQudGFibGUucDEpIDwtIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzDQoNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfcmVsYXhlZF9QMDIpDQp7DQogIHJlbGF4ZWQudGltZXMgPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHAgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09InJlbGF4ZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgDQogIHRvLmJlLmRyb3BwZWQgPC0gdmVjdG9yKCkNCiAgDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgocmVsYXhlZC50aW1lcykpKQ0KICB7DQogICAgdG8uYmUuZHJvcHBlZCA8LSBjKHRvLmJlLmRyb3BwZWQsIHdoaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMSIpICYgZGF0YSR1bml4LnRpbWUudmlkZW8gPiByZWxheGVkLnRpbWVzW2ldKVsxOm1heC53aW5kb3cuc2l6ZV0pDQogICAgDQogIH0NCiAgDQogIHRvLmJlLmRyb3BwZWQgPC0gdG8uYmUuZHJvcHBlZFshaXMubmEodG8uYmUuZHJvcHBlZCldICNyZW1vdmUgTkEgd2hlbiBtYXgud2luZG93LnNpemUgZ29lcyBvdXQgb2YgYm91bmRzIGJlY2F1c2UgdGhlIGVuZCBvZiBjb2xsYWJvcmF0aXZlIGFjdHMgZm9yIHRoYXQgcGFydGljaXBhbnQgaXMgcmVhY2hlZA0KICANCiAgZGF0YS5rZXB0IDwtIGRhdGFbLXRvLmJlLmRyb3BwZWQsXSAjZGF0YS5rZXB0IGlzIHRoZSBkYXRhIHdpdGhvdXQgZW1vdGlvbmFsIGNodW5rcw0KICANCiAgZGF0YS5rZXB0IDwtIGRhdGEua2VwdFtkYXRhLmtlcHQkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMSIpLF0NCiAgDQogICNLZWVwIGEgbnVtYmVyIG9mIGxpbmVzIHRoYXQgaXMgYSBtdWx0aXBsZSBvZiBtYXgud2luZG93cy5zaXplID0gbnVtYmVyIG9mIG5vbi1lbW90aW9uYWwgY2h1bmtzDQogIA0KICBuIDwtIG5yb3coZGF0YS5rZXB0KQ0KICBkYXRhLmtlcHQgPC0gZGF0YS5rZXB0W2MoMToobi0obiUlbWF4LndpbmRvdy5zaXplKSkpLF0NCiAgDQogIGxlbmd0aChkYXRhLmtlcHQkcGFydGljaXBhbnQpDQogIA0KICANCiAgcmVzdWx0cyA8LSBjKCkNCiAgZm9yIChwcm9jZXNzIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKQ0KICAgIHsNCiAgICByZXN1bHRzIDwtIGMocmVzdWx0cywgc3VtKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcz09cHJvY2VzcykpDQogICAgfQ0KICANCiAgbm9uLnJlbGF4ZWQudGFibGUucDFbLHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKV0gPC0gcmVzdWx0cy8obGVuZ3RoKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyklLyVtYXgud2luZG93LnNpemUpDQogIHJlc3VsdHMgPC0gYygpDQogIA0KfQ0KDQpub24ucmVsYXhlZC50YWJsZS5wMQ0KDQpub24ucmVsYXhlZC50YWJsZSA8LSBjYmluZChub24ucmVsYXhlZC50YWJsZS5wMSwgbm9uLnJlbGF4ZWQudGFibGUucDIpDQpub24ucmVsYXhlZC50YWJsZQ0KYGBgDQoNCiMjIyBDb25maWRlbnQNCg0KYGBge3J9DQojRmluZCBjYXNlcyBhdmFpbGFibGUgZm9yIGNvbmZpZGVudCwgaS5lLiwgdGhlIHBhcnRpY2lwYW50cyBmb3Igd2hpY2ggb25lIG9yIG1vcmUgc2hhcmluZyBvZiBjb25maWRlbnQgb2NjdXJlZA0KDQpjb25maWRlbnQuY2FzZXMgPC0gYygpDQoNCmVtb3Rpb24gPSAiY29uZmlkZW50Ig0KZm9yIChwYXJ0aWNpcGFudCBpbiBwYXJ0aWNpcGFudHNfZWF0KSB7DQogICAgcHJpbnQocGFzdGUoIlBvdXIgbGUgcGFydGljaXBhbnQgIiwgcGFydGljaXBhbnQsIiBpbCB5IGEiLCBsZW5ndGgoZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhcnRpY2lwYW50ICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSBlbW90aW9uKSxjKCJzaGFyZWQuZW1vdGlvbiIpXSksImNvcnJlc3BvbmRhbmNlKHMpIikpDQogICAgY29uZmlkZW50LmNhc2VzW3BhcnRpY2lwYW50XSA8LSBsZW5ndGgoZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhcnRpY2lwYW50ICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSBlbW90aW9uKSxjKCJzaGFyZWQuZW1vdGlvbiIpXSkNCn0NCg0KY29uZmlkZW50LmF2YWlsYWJsZS5jYXNlcyA8LSBjb25maWRlbnQuY2FzZXNbY29uZmlkZW50LmNhc2VzICE9IDBdDQpjb25maWRlbnQuYXZhaWxhYmxlLmNhc2VzDQpsZW5ndGgoY29uZmlkZW50LmF2YWlsYWJsZS5jYXNlcykNCm5hbWVzKGNvbmZpZGVudC5hdmFpbGFibGUuY2FzZXMpDQoNCmBgYA0KDQpgYGB7cn0NCiNjb25maWRlbnQgc2FtcGxlDQpwYXJ0aWNpcGFudHNfZWF0X2NvbmZpZGVudF9QMDEgPC0gYygiRDA5UDAxIiwiRDE2UDAxIiwiRDI2UDAxIiwiRDI3UDAxIiwiRDI5UDAxIikNCnBhcnRpY2lwYW50c19lYXRfY29uZmlkZW50X1AwMiA8LSBjKCJEMDJQMDIiLCJEMDVQMDIiLCJEMTZQMDIiLCJEMjZQMDIiKQ0KYGBgDQoNCmBgYHtyfQ0KI0NvbXB1dGUgdGhlIHJlYWwtdGltZSB1c2UgZm9yIHRoZSBlbW90aW9uIGNvbmZpZGVudA0KDQojc2VsZWN0IHRoZSBzdWJzZXQgb2YgY29sbGFib3JhdGl2ZSBwcm9jZXNzZXMgZm9yIGEgZ2l2ZW4gcGFydGljaXBhbnQuIEZvciB0aGUgZW1vdGlvbiBjb25maWRlbnQsIHRoZSAobWF4LndpbmRvd3Muc2l6ZSkgY29sbGFib3JhdGl2ZSBwcm9jZXNzZXMgb2YgdGhlIG90aGVyJ3MgcGFydG5lciBmcm9tIHRoZSBzYW1lIGR5YWQgYXJlIHNlbGVjdGVkDQoNCiNQMDIgcGFydGljaXBhbnRzDQpuIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bGVuZ3RoKGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSxuY29sPTApDQpjb25maWRlbnQudGFibGUucDIgPC0gZGF0YS5mcmFtZShuKQ0Kcm93bmFtZXMoY29uZmlkZW50LnRhYmxlLnAyKSA8LSBjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcw0KDQpmb3IgKHAgaW4gcGFydGljaXBhbnRzX2VhdF9jb25maWRlbnRfUDAxKQ0Kew0KICBtIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bWF4LndpbmRvdy5zaXplLG5jb2w9MCkNCiAgY29uZmlkZW50LmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlIDwtIGRhdGEuZnJhbWUobSkNCg0KICBjb25maWRlbnQudGltZXMgPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHAgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09ImNvbmZpZGVudCIpLGMoInVuaXgudGltZS52aWRlbyIpXQ0KICBjb25maWRlbnQudGltZXMubGVuZ3RoIDwtIGxlbmd0aChjb25maWRlbnQudGltZXMpDQoNCiAgZm9yIChpIGluIHNlcSgxOmxlbmd0aChjb25maWRlbnQudGltZXMpKSkNCiAgew0KICAgIGNvbmZpZGVudC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVsscGFzdGUwKCJvY2N1cmVuY2UiLGkpXSA8LSBkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMiIpICYgZGF0YSR1bml4LnRpbWUudmlkZW8gPiBjb25maWRlbnQudGltZXNbaV0pLGMoImNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzIildWzE6bWF4LndpbmRvdy5zaXplXSANCiAgfQ0KDQogIGNvbmZpZGVudC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZQ0KICAjY2hlY2sgaWYgdGhlIGVtb3Rpb24gd2luZG93cyBhbGwgaGF2ZSBhIGxlbmd0aCBvZiBtYXgud2luZG93LnNpemUNCiAgI3doZW4gaXQgaXMgbm90IHRoZSBjYXNlLCB0aGUgZW1vdGlvbiB3aW5kb3cgaXMgcmVtb3ZlZA0KICBmb3IgKGNvbCBpbiBjb2xuYW1lcyhjb25maWRlbnQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUpKXsNCiAgICBpZiAoYW55TkEoY29uZmlkZW50LmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlWyxjb2xdKSkgew0KICAgICAgY29uZmlkZW50LnRpbWVzLmxlbmd0aCA8LSBjb25maWRlbnQudGltZXMubGVuZ3RoLTENCiAgICAgIGNvbmZpZGVudC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSA9IGNvbmZpZGVudC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVssIShuYW1lcyhjb25maWRlbnQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUpICVpbiUgYyhjb2wpKV0NCiAgICB9DQogIH0NCiAgDQogICNjb21wdXRlIHRoZSByZWFsLXRpbWUgdXNlIGZvciBldmVyeSBjb2xsYWJvcmF0aXZlIHByb2Nlc3MNCiAgeCA8LSBjKCkNCiAgZm9yIChpIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKQ0KICB7DQogICAgeFtpXSA8LSBsZW5ndGgoY29uZmlkZW50LmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlW2NvbmZpZGVudC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSA9PSBpXSkNCiAgfQ0KICB4IDwtIHgvY29uZmlkZW50LnRpbWVzLmxlbmd0aCAjbnVtYmVyIG9mIGVtb3Rpb24gd2luZG93cw0KICBjb25maWRlbnQudGFibGUucDJbLHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjIiKV0gPSB4DQp9DQoNCmNvbmZpZGVudC50YWJsZS5wMg0KDQojUDAxIHBhcnRpY2lwYW50cw0KbiA8LSBtYXRyaXgoZGF0YT1OQSxucm93PWxlbmd0aChjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyksbmNvbD0wKQ0KY29uZmlkZW50LnRhYmxlLnAxIDwtIGRhdGEuZnJhbWUobikNCnJvd25hbWVzKGNvbmZpZGVudC50YWJsZS5wMSkgPC0gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfY29uZmlkZW50X1AwMikNCnsNCiAgbSA8LSBtYXRyaXgoZGF0YT1OQSxucm93PW1heC53aW5kb3cuc2l6ZSxuY29sPTApDQogIGNvbmZpZGVudC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSA8LSBkYXRhLmZyYW1lKG0pDQoNCiAgY29uZmlkZW50LnRpbWVzIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSAiY29uZmlkZW50IiksYygidW5peC50aW1lLnZpZGVvIildDQogIGNvbmZpZGVudC50aW1lcy5sZW5ndGggPC0gbGVuZ3RoKGNvbmZpZGVudC50aW1lcykNCiAgDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgoY29uZmlkZW50LnRpbWVzKSkpDQogIHsNCiAgICBjb25maWRlbnQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLHBhc3RlMCgib2NjdXJlbmNlIixpKV0gPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKSAmIGRhdGEkdW5peC50aW1lLnZpZGVvID4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uZmlkZW50LnRpbWVzW2ldKSxjKCJjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyIpXVsxOm1heC53aW5kb3cuc2l6ZV0gDQogIH0NCg0KICBjb25maWRlbnQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUNCiAgDQogICNjaGVjayBpZiB0aGUgZW1vdGlvbiB3aW5kb3dzIGFsbCBoYXZlIGEgbGVuZ3RoIG9mIG1heC53aW5kb3cuc2l6ZQ0KICAjd2hlbiBpdCBpcyBub3QgdGhlIGNhc2UsIHRoZSBlbW90aW9uIHdpbmRvdyBpcyByZW1vdmVkDQogIGZvciAoY29sIGluIGNvbG5hbWVzKGNvbmZpZGVudC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkpew0KICAgIGlmIChhbnlOQShjb25maWRlbnQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLGNvbF0pKSB7DQogICAgICBjb25maWRlbnQudGltZXMubGVuZ3RoIDwtIGNvbmZpZGVudC50aW1lcy5sZW5ndGgtMQ0KICAgICAgY29uZmlkZW50LmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlID0gY29uZmlkZW50LmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlWywhKG5hbWVzKGNvbmZpZGVudC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkgJWluJSBjKGNvbCkpXQ0KICAgIH0NCiAgfQ0KICANCiAgI2NvbXB1dGUgdGhlIHJlYWwtdGltZSB1c2UgZm9yIGV2ZXJ5IGNvbGxhYm9yYXRpdmUgcHJvY2Vzcw0KICB4IDwtIGMoKQ0KICBmb3IgKGkgaW4gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpDQogIHsNCiAgICB4W2ldIDwtIGxlbmd0aChjb25maWRlbnQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbY29uZmlkZW50LmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlID09IGldKQ0KICB9DQogIHggPC0geC9jb25maWRlbnQudGltZXMubGVuZ3RoICNudW1iZXIgb2YgZW1vdGlvbiB3aW5kb3dzDQogIGNvbmZpZGVudC50YWJsZS5wMVsscGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMSIpXSA9IHgNCn0NCg0KY29uZmlkZW50LnRhYmxlLnAxICAgIA0KDQpjb25maWRlbnQudGFibGUgPC0gY2JpbmQoY29uZmlkZW50LnRhYmxlLnAxLCBjb25maWRlbnQudGFibGUucDIpDQpjb25maWRlbnQudGFibGUNCmBgYA0KDQpgYGB7cn0NCiNDb21wdXRlIHRoZSByZWxhdGl2ZSB1c2Ugd2hlbiBubyBlbW90aW9uIGNvbmZpZGVudA0KDQojU2VsZWN0IGEgc3Vic2V0IG9mIHRoZSBkYXRhIG5vdCBpbmNsdWRpbmcgdGhlIGVtb3Rpb25hbCBjb2xsYWJvcmF0aXZlIHByb2Nlc3NlcyB0aGF0IGFyZSBlbWl0dGVkIGp1c3QgYWZ0ZXIgdGhlIGVtb3Rpb24gb2YgaW50ZXJlc3QNCg0KI3Jlc3VsdHMgZm9yIFAwMiBwYXJ0aWNpcGFudHNfZWF0DQoNCm4gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1sZW5ndGgoY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpLG5jb2w9MCkNCm5vbi5jb25maWRlbnQudGFibGUucDIgPC0gZGF0YS5mcmFtZShuKQ0Kcm93bmFtZXMobm9uLmNvbmZpZGVudC50YWJsZS5wMikgPC0gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfY29uZmlkZW50X1AwMSkNCnsNCiAgY29uZmlkZW50LnRpbWVzIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSJjb25maWRlbnQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgDQogIHRvLmJlLmRyb3BwZWQgPC0gdmVjdG9yKCkNCiAgDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgoY29uZmlkZW50LnRpbWVzKSkpDQogIHsNCiAgICB0by5iZS5kcm9wcGVkIDwtIGModG8uYmUuZHJvcHBlZCwgd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIyIikgJiBkYXRhJHVuaXgudGltZS52aWRlbyA+IGNvbmZpZGVudC50aW1lc1tpXSlbMTptYXgud2luZG93LnNpemVdKQ0KICAgIA0KICB9DQogIA0KICB0by5iZS5kcm9wcGVkIDwtIHRvLmJlLmRyb3BwZWRbIWlzLm5hKHRvLmJlLmRyb3BwZWQpXSAjcmVtb3ZlIE5BIHdoZW4gbWF4LndpbmRvdy5zaXplIGdvZXMgb3V0IG9mIGJvdW5kcyBiZWNhdXNlIHRoZSBlbmQgb2YgY29sbGFib3JhdGl2ZSBhY3RzIGZvciB0aGF0IHBhcnRpY2lwYW50IGlzIHJlYWNoZWQNCiAgDQogIGRhdGEua2VwdCA8LSBkYXRhWy10by5iZS5kcm9wcGVkLF0gI2RhdGEua2VwdCBpcyB0aGUgZGF0YSB3aXRob3V0IGVtb3Rpb25hbCBjaHVua3MNCiAgDQogIGRhdGEua2VwdCA8LSBkYXRhLmtlcHRbZGF0YS5rZXB0JHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjIiKSxdDQogIA0KICAjS2VlcCBhIG51bWJlciBvZiBsaW5lcyB0aGF0IGlzIGEgbXVsdGlwbGUgb2YgbWF4LndpbmRvd3Muc2l6ZSA9IG51bWJlciBvZiBub24tZW1vdGlvbmFsIGNodW5rcw0KICANCiAgbiA8LSBucm93KGRhdGEua2VwdCkNCiAgZGF0YS5rZXB0IDwtIGRhdGEua2VwdFtjKDE6KG4tKG4lJW1heC53aW5kb3cuc2l6ZSkpKSxdDQogIA0KICBsZW5ndGgoZGF0YS5rZXB0JHBhcnRpY2lwYW50KQ0KICANCiAgDQogIHJlc3VsdHMgPC0gYygpDQogIGZvciAocHJvY2VzcyBpbiBjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcykNCiAgICB7DQogICAgcmVzdWx0cyA8LSBjKHJlc3VsdHMsIHN1bShkYXRhLmtlcHQkY29sbGFib3JhdGl2ZS5wcm9jZXNzZXM9PXByb2Nlc3MpKQ0KICAgIH0NCiAgDQogIG5vbi5jb25maWRlbnQudGFibGUucDJbLHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjIiKV0gPC0gcmVzdWx0cy8obGVuZ3RoKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyklLyVtYXgud2luZG93LnNpemUpDQogIHJlc3VsdHMgPC0gYygpDQogIA0KfQ0KDQpub24uY29uZmlkZW50LnRhYmxlLnAyDQoNCiNyZXN1bHRzIGZvciBQMDEgcGFydGljaXBhbnRzX2VhdA0KDQpuIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bGVuZ3RoKGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSxuY29sPTApDQpub24uY29uZmlkZW50LnRhYmxlLnAxIDwtIGRhdGEuZnJhbWUobikNCnJvd25hbWVzKG5vbi5jb25maWRlbnQudGFibGUucDEpIDwtIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzDQoNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfY29uZmlkZW50X1AwMikNCnsNCiAgY29uZmlkZW50LnRpbWVzIDwtIGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSJjb25maWRlbnQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgDQogIHRvLmJlLmRyb3BwZWQgPC0gdmVjdG9yKCkNCiAgDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgoY29uZmlkZW50LnRpbWVzKSkpDQogIHsNCiAgICB0by5iZS5kcm9wcGVkIDwtIGModG8uYmUuZHJvcHBlZCwgd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIxIikgJiBkYXRhJHVuaXgudGltZS52aWRlbyA+IGNvbmZpZGVudC50aW1lc1tpXSlbMTptYXgud2luZG93LnNpemVdKQ0KICAgIA0KICB9DQogIA0KICB0by5iZS5kcm9wcGVkIDwtIHRvLmJlLmRyb3BwZWRbIWlzLm5hKHRvLmJlLmRyb3BwZWQpXSAjcmVtb3ZlIE5BIHdoZW4gbWF4LndpbmRvdy5zaXplIGdvZXMgb3V0IG9mIGJvdW5kcyBiZWNhdXNlIHRoZSBlbmQgb2YgY29sbGFib3JhdGl2ZSBhY3RzIGZvciB0aGF0IHBhcnRpY2lwYW50IGlzIHJlYWNoZWQNCiAgDQogIGRhdGEua2VwdCA8LSBkYXRhWy10by5iZS5kcm9wcGVkLF0gI2RhdGEua2VwdCBpcyB0aGUgZGF0YSB3aXRob3V0IGVtb3Rpb25hbCBjaHVua3MNCiAgDQogIGRhdGEua2VwdCA8LSBkYXRhLmtlcHRbZGF0YS5rZXB0JHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKSxdDQogIA0KICAjS2VlcCBhIG51bWJlciBvZiBsaW5lcyB0aGF0IGlzIGEgbXVsdGlwbGUgb2YgbWF4LndpbmRvd3Muc2l6ZSA9IG51bWJlciBvZiBub24tZW1vdGlvbiBjaHVua3MNCiAgDQogIG4gPC0gbnJvdyhkYXRhLmtlcHQpDQogIGRhdGEua2VwdCA8LSBkYXRhLmtlcHRbYygxOihuLShuJSVtYXgud2luZG93LnNpemUpKSksXQ0KICANCiAgbGVuZ3RoKGRhdGEua2VwdCRwYXJ0aWNpcGFudCkNCiAgDQogIA0KICByZXN1bHRzIDwtIGMoKQ0KICBmb3IgKHByb2Nlc3MgaW4gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpDQogICAgew0KICAgIHJlc3VsdHMgPC0gYyhyZXN1bHRzLCBzdW0oZGF0YS5rZXB0JGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzPT1wcm9jZXNzKSkNCiAgICB9DQogIA0KICBub24uY29uZmlkZW50LnRhYmxlLnAxWyxwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIxIildIDwtIHJlc3VsdHMvKGxlbmd0aChkYXRhLmtlcHQkY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpJS8lbWF4LndpbmRvdy5zaXplKQ0KICByZXN1bHRzIDwtIGMoKQ0KICANCn0NCg0Kbm9uLmNvbmZpZGVudC50YWJsZS5wMQ0KDQpub24uY29uZmlkZW50LnRhYmxlIDwtIGNiaW5kKG5vbi5jb25maWRlbnQudGFibGUucDEsIG5vbi5jb25maWRlbnQudGFibGUucDIpDQpub24uY29uZmlkZW50LnRhYmxlDQpgYGANCiMjIyBDb25mdXNlZA0KDQpgYGB7cn0NCiNGaW5kIGNhc2VzIGF2YWlsYWJsZSBmb3IgY29uZnVzZWQsIGkuZS4sIHRoZSBwYXJ0aWNpcGFudHMgZm9yIHdoaWNoIG9uZSBvciBtb3JlIHNoYXJpbmcgb2YgY29uZnVzZWQgb2NjdXJlZA0KDQpjb25mdXNlZC5jYXNlcyA8LSBjKCkNCg0KZW1vdGlvbiA9ICJjb25mdXNlZCINCmZvciAocGFydGljaXBhbnQgaW4gcGFydGljaXBhbnRzX2VhdCkgew0KICAgIHByaW50KHBhc3RlKCJQb3VyIGxlIHBhcnRpY2lwYW50ICIsIHBhcnRpY2lwYW50LCIgaWwgeSBhIiwgbGVuZ3RoKGRhdGFbd2hpY2goZGF0YSRwYXJ0aWNpcGFudCA9PSBwYXJ0aWNpcGFudCAmIGRhdGEkc2hhcmVkLmVtb3Rpb24gPT0gZW1vdGlvbiksYygic2hhcmVkLmVtb3Rpb24iKV0pLCJjb3JyZXNwb25kYW5jZShzKSIpKQ0KICAgIGNvbmZ1c2VkLmNhc2VzW3BhcnRpY2lwYW50XSA8LSBsZW5ndGgoZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhcnRpY2lwYW50ICYgZGF0YSRzaGFyZWQuZW1vdGlvbiA9PSBlbW90aW9uKSxjKCJzaGFyZWQuZW1vdGlvbiIpXSkNCn0NCg0KY29uZnVzZWQuYXZhaWxhYmxlLmNhc2VzIDwtIGNvbmZ1c2VkLmNhc2VzW2NvbmZ1c2VkLmNhc2VzICE9IDBdDQpjb25mdXNlZC5hdmFpbGFibGUuY2FzZXMNCmxlbmd0aChjb25mdXNlZC5hdmFpbGFibGUuY2FzZXMpDQpuYW1lcyhjb25mdXNlZC5hdmFpbGFibGUuY2FzZXMpDQpgYGANCg0KYGBge3J9DQojY29uZnVzZWQgc2FtcGxlDQpwYXJ0aWNpcGFudHNfZWF0X2NvbmZ1c2VkX1AwMSA8LSBjKCJEMDVQMDEiLCJEMDdQMDEiLCJEMTNQMDEiLCJEMjlQMDEiKQ0KcGFydGljaXBhbnRzX2VhdF9jb25mdXNlZF9QMDIgPC0gYygiRDA3UDAyIiwiRDI2UDAyIikNCmBgYA0KDQoNCmBgYHtyfQ0KI0NvbXB1dGUgdGhlIHJlYWwtdGltZSB1c2UgZm9yIHRoZSBlbW90aW9uIGNvbmZ1c2VkDQoNCiNzZWxlY3QgdGhlIHN1YnNldCBvZiBjb2xsYWJvcmF0aXZlIHByb2Nlc3NlcyBmb3IgYSBnaXZlbiBwYXJ0aWNpcGFudC4gRm9yIHRoZSBlbW90aW9uIGNvbmZ1c2VkLCB0aGUgKG1heC53aW5kb3dzLnNpemUpIGNvbGxhYm9yYXRpdmUgcHJvY2Vzc2VzIG9mIHRoZSBvdGhlcidzIHBhcnRuZXIgZnJvbSB0aGUgc2FtZSBkeWFkIGFyZSBzZWxlY3RlZA0KDQojUDAyIHBhcnRpY2lwYW50cw0KbiA8LSBtYXRyaXgoZGF0YT1OQSxucm93PWxlbmd0aChjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyksbmNvbD0wKQ0KY29uZnVzZWQudGFibGUucDIgPC0gZGF0YS5mcmFtZShuKQ0Kcm93bmFtZXMoY29uZnVzZWQudGFibGUucDIpIDwtIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzDQoNCmZvciAocCBpbiBwYXJ0aWNpcGFudHNfZWF0X2NvbmZ1c2VkX1AwMSkNCnsNCiAgbSA8LSBtYXRyaXgoZGF0YT1OQSxucm93PW1heC53aW5kb3cuc2l6ZSxuY29sPTApDQogIGNvbmZ1c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlIDwtIGRhdGEuZnJhbWUobSkNCg0KICBjb25mdXNlZC50aW1lcyA8LSBkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcCAmIGRhdGEkc2hhcmVkLmVtb3Rpb24gPT0iY29uZnVzZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgY29uZnVzZWQudGltZXMubGVuZ3RoIDwtIGxlbmd0aChjb25mdXNlZC50aW1lcykNCg0KICBmb3IgKGkgaW4gc2VxKDE6bGVuZ3RoKGNvbmZ1c2VkLnRpbWVzKSkpDQogIHsNCiAgICBjb25mdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVsscGFzdGUwKCJvY2N1cmVuY2UiLGkpXSA8LSBkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMiIpICYgZGF0YSR1bml4LnRpbWUudmlkZW8gPiBjb25mdXNlZC50aW1lc1tpXSksYygiY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMiKV1bMTptYXgud2luZG93LnNpemVdIA0KICB9DQoNCiAgY29uZnVzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUNCiAgI2NoZWNrIGlmIHRoZSBlbW90aW9uIHdpbmRvd3MgYWxsIGhhdmUgYSBsZW5ndGggb2YgbWF4LndpbmRvdy5zaXplDQogICN3aGVuIGl0IGlzIG5vdCB0aGUgY2FzZSwgdGhlIGVtb3Rpb24gd2luZG93IGlzIHJlbW92ZWQNCiAgZm9yIChjb2wgaW4gY29sbmFtZXMoY29uZnVzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUpKXsNCiAgICBpZiAoYW55TkEoY29uZnVzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLGNvbF0pKSB7DQogICAgICBjb25mdXNlZC50aW1lcy5sZW5ndGggPC0gY29uZnVzZWQudGltZXMubGVuZ3RoLTENCiAgICAgIGNvbmZ1c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlID0gY29uZnVzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLCEobmFtZXMoY29uZnVzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUpICVpbiUgYyhjb2wpKV0NCiAgICB9DQogIH0NCiAgDQogICNjb21wdXRlIHRoZSByZWFsLXRpbWUgdXNlIGZvciBldmVyeSBjb2xsYWJvcmF0aXZlIHByb2Nlc3MNCiAgeCA8LSBjKCkNCiAgZm9yIChpIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKQ0KICB7DQogICAgeFtpXSA8LSBsZW5ndGgoY29uZnVzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbY29uZnVzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUgPT0gaV0pDQogIH0NCiAgeCA8LSB4L2NvbmZ1c2VkLnRpbWVzLmxlbmd0aCAjbnVtYmVyIG9mIGVtb3Rpb24gd2luZG93cw0KICBjb25mdXNlZC50YWJsZS5wMlsscGFzdGUwKHN1YnN0cihwLCAxLCA1KSwiMiIpXSA9IHgNCn0NCg0KY29uZnVzZWQudGFibGUucDINCg0KI1AwMSBwYXJ0aWNpcGFudHMNCm4gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1sZW5ndGgoY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpLG5jb2w9MCkNCmNvbmZ1c2VkLnRhYmxlLnAxIDwtIGRhdGEuZnJhbWUobikNCnJvd25hbWVzKGNvbmZ1c2VkLnRhYmxlLnAxKSA8LSBjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcw0KDQpmb3IgKHAgaW4gcGFydGljaXBhbnRzX2VhdF9jb25mdXNlZF9QMDIpDQp7DQogIG0gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1tYXgud2luZG93LnNpemUsbmNvbD0wKQ0KICBjb25mdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSA8LSBkYXRhLmZyYW1lKG0pDQoNCiAgY29uZnVzZWQudGltZXMgPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHAgJiBkYXRhJHNoYXJlZC5lbW90aW9uID09ICJjb25mdXNlZCIpLGMoInVuaXgudGltZS52aWRlbyIpXQ0KICBjb25mdXNlZC50aW1lcy5sZW5ndGggPC0gbGVuZ3RoKGNvbmZ1c2VkLnRpbWVzKQ0KICANCiAgZm9yIChpIGluIHNlcSgxOmxlbmd0aChjb25mdXNlZC50aW1lcykpKQ0KICB7DQogICAgY29uZnVzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGVbLHBhc3RlMCgib2NjdXJlbmNlIixpKV0gPC0gZGF0YVt3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKSAmIGRhdGEkdW5peC50aW1lLnZpZGVvID4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uZnVzZWQudGltZXNbaV0pLGMoImNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzIildWzE6bWF4LndpbmRvdy5zaXplXSANCiAgfQ0KDQogIGNvbmZ1c2VkLmNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzLnRhYmxlDQogIA0KICAjY2hlY2sgaWYgdGhlIGVtb3Rpb24gd2luZG93cyBhbGwgaGF2ZSBhIGxlbmd0aCBvZiBtYXgud2luZG93LnNpemUNCiAgI3doZW4gaXQgaXMgbm90IHRoZSBjYXNlLCB0aGUgZW1vdGlvbiB3aW5kb3cgaXMgcmVtb3ZlZA0KICBmb3IgKGNvbCBpbiBjb2xuYW1lcyhjb25mdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkpew0KICAgIGlmIChhbnlOQShjb25mdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVssY29sXSkpIHsNCiAgICAgIGNvbmZ1c2VkLnRpbWVzLmxlbmd0aCA8LSBjb25mdXNlZC50aW1lcy5sZW5ndGgtMQ0KICAgICAgY29uZnVzZWQuY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMudGFibGUgPSBjb25mdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVssIShuYW1lcyhjb25mdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSkgJWluJSBjKGNvbCkpXQ0KICAgIH0NCiAgfQ0KICANCiAgI2NvbXB1dGUgdGhlIHJlYWwtdGltZSB1c2UgZm9yIGV2ZXJ5IGNvbGxhYm9yYXRpdmUgcHJvY2Vzcw0KICB4IDwtIGMoKQ0KICBmb3IgKGkgaW4gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpDQogIHsNCiAgICB4W2ldIDwtIGxlbmd0aChjb25mdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZVtjb25mdXNlZC5jb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcy50YWJsZSA9PSBpXSkNCiAgfQ0KICB4IDwtIHgvY29uZnVzZWQudGltZXMubGVuZ3RoICNudW1iZXIgb2YgZW1vdGlvbiB3aW5kb3dzDQogIGNvbmZ1c2VkLnRhYmxlLnAxWyxwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIxIildID0geA0KfQ0KDQpjb25mdXNlZC50YWJsZS5wMSAgICANCg0KY29uZnVzZWQudGFibGUgPC0gY2JpbmQoY29uZnVzZWQudGFibGUucDEsIGNvbmZ1c2VkLnRhYmxlLnAyKQ0KY29uZnVzZWQudGFibGUNCmBgYA0KDQpgYGB7cn0NCiNDb21wdXRlIHRoZSByZWxhdGl2ZSB1c2Ugd2hlbiBubyBlbW90aW9uIGNvbmZ1c2VkDQoNCiNTZWxlY3QgYSBzdWJzZXQgb2YgdGhlIGRhdGEgbm90IGluY2x1ZGluZyB0aGUgZW1vdGlvbmFsIGNvbGxhYm9yYXRpdmUgcHJvY2Vzc2VzIHRoYXQgYXJlIGVtaXR0ZWQganVzdCBhZnRlciB0aGUgZW1vdGlvbiBvZiBpbnRlcmVzdA0KDQojcmVzdWx0cyBmb3IgUDAyIHBhcnRpY2lwYW50c19lYXQNCg0KbiA8LSBtYXRyaXgoZGF0YT1OQSxucm93PWxlbmd0aChjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyksbmNvbD0wKQ0Kbm9uLmNvbmZ1c2VkLnRhYmxlLnAyIDwtIGRhdGEuZnJhbWUobikNCnJvd25hbWVzKG5vbi5jb25mdXNlZC50YWJsZS5wMikgPC0gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfY29uZnVzZWRfUDAxKQ0Kew0KICBjb25mdXNlZC50aW1lcyA8LSBkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcCAmIGRhdGEkc2hhcmVkLmVtb3Rpb24gPT0iY29uZnVzZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgDQogIHRvLmJlLmRyb3BwZWQgPC0gdmVjdG9yKCkNCiAgDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgoY29uZnVzZWQudGltZXMpKSkNCiAgew0KICAgIHRvLmJlLmRyb3BwZWQgPC0gYyh0by5iZS5kcm9wcGVkLCB3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjIiKSAmIGRhdGEkdW5peC50aW1lLnZpZGVvID4gY29uZnVzZWQudGltZXNbaV0pWzE6bWF4LndpbmRvdy5zaXplXSkNCiAgICANCiAgfQ0KICANCiAgdG8uYmUuZHJvcHBlZCA8LSB0by5iZS5kcm9wcGVkWyFpcy5uYSh0by5iZS5kcm9wcGVkKV0gI3JlbW92ZSBOQSB3aGVuIG1heC53aW5kb3cuc2l6ZSBnb2VzIG91dCBvZiBib3VuZHMgYmVjYXVzZSB0aGUgZW5kIG9mIGNvbGxhYm9yYXRpdmUgYWN0cyBmb3IgdGhhdCBwYXJ0aWNpcGFudCBpcyByZWFjaGVkDQogIA0KICBkYXRhLmtlcHQgPC0gZGF0YVstdG8uYmUuZHJvcHBlZCxdICNkYXRhLmtlcHQgaXMgdGhlIGRhdGEgd2l0aG91dCBlbW90aW9uYWwgY2h1bmtzDQogIA0KICBkYXRhLmtlcHQgPC0gZGF0YS5rZXB0W2RhdGEua2VwdCRwYXJ0aWNpcGFudCA9PSBwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIyIiksXQ0KICANCiAgI0tlZXAgYSBudW1iZXIgb2YgbGluZXMgdGhhdCBpcyBhIG11bHRpcGxlIG9mIG1heC53aW5kb3dzLnNpemUgPSBudW1iZXIgb2Ygbm9uLWVtb3Rpb25hbCBjaHVua3MNCiAgDQogIG4gPC0gbnJvdyhkYXRhLmtlcHQpDQogIGRhdGEua2VwdCA8LSBkYXRhLmtlcHRbYygxOihuLShuJSVtYXgud2luZG93LnNpemUpKSksXQ0KICANCiAgbGVuZ3RoKGRhdGEua2VwdCRwYXJ0aWNpcGFudCkNCiAgDQogIA0KICByZXN1bHRzIDwtIGMoKQ0KICBmb3IgKHByb2Nlc3MgaW4gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpDQogICAgew0KICAgIHJlc3VsdHMgPC0gYyhyZXN1bHRzLCBzdW0oZGF0YS5rZXB0JGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzPT1wcm9jZXNzKSkNCiAgICB9DQogIA0KICBub24uY29uZnVzZWQudGFibGUucDJbLHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjIiKV0gPC0gcmVzdWx0cy8obGVuZ3RoKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcyklLyVtYXgud2luZG93LnNpemUpDQogIHJlc3VsdHMgPC0gYygpDQogIA0KfQ0KDQpub24uY29uZnVzZWQudGFibGUucDINCg0KI3Jlc3VsdHMgZm9yIFAwMSBwYXJ0aWNpcGFudHNfZWF0DQoNCm4gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1sZW5ndGgoY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpLG5jb2w9MCkNCm5vbi5jb25mdXNlZC50YWJsZS5wMSA8LSBkYXRhLmZyYW1lKG4pDQpyb3duYW1lcyhub24uY29uZnVzZWQudGFibGUucDEpIDwtIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzDQoNCg0KZm9yIChwIGluIHBhcnRpY2lwYW50c19lYXRfY29uZnVzZWRfUDAyKQ0Kew0KICBjb25mdXNlZC50aW1lcyA8LSBkYXRhW3doaWNoKGRhdGEkcGFydGljaXBhbnQgPT0gcCAmIGRhdGEkc2hhcmVkLmVtb3Rpb24gPT0iY29uZnVzZWQiKSxjKCJ1bml4LnRpbWUudmlkZW8iKV0NCiAgDQogIHRvLmJlLmRyb3BwZWQgPC0gdmVjdG9yKCkNCiAgDQogIGZvciAoaSBpbiBzZXEoMTpsZW5ndGgoY29uZnVzZWQudGltZXMpKSkNCiAgew0KICAgIHRvLmJlLmRyb3BwZWQgPC0gYyh0by5iZS5kcm9wcGVkLCB3aGljaChkYXRhJHBhcnRpY2lwYW50ID09IHBhc3RlMChzdWJzdHIocCwgMSwgNSksIjEiKSAmIGRhdGEkdW5peC50aW1lLnZpZGVvID4gY29uZnVzZWQudGltZXNbaV0pWzE6bWF4LndpbmRvdy5zaXplXSkNCiAgICANCiAgfQ0KICANCiAgdG8uYmUuZHJvcHBlZCA8LSB0by5iZS5kcm9wcGVkWyFpcy5uYSh0by5iZS5kcm9wcGVkKV0gI3JlbW92ZSBOQSB3aGVuIG1heC53aW5kb3cuc2l6ZSBnb2VzIG91dCBvZiBib3VuZHMgYmVjYXVzZSB0aGUgZW5kIG9mIGNvbGxhYm9yYXRpdmUgYWN0cyBmb3IgdGhhdCBwYXJ0aWNpcGFudCBpcyByZWFjaGVkDQogIA0KICBkYXRhLmtlcHQgPC0gZGF0YVstdG8uYmUuZHJvcHBlZCxdICNkYXRhLmtlcHQgaXMgdGhlIGRhdGEgd2l0aG91dCBlbW90aW9uYWwgY2h1bmtzDQogIA0KICBkYXRhLmtlcHQgPC0gZGF0YS5rZXB0W2RhdGEua2VwdCRwYXJ0aWNpcGFudCA9PSBwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIxIiksXQ0KICANCiAgI0tlZXAgYSBudW1iZXIgb2YgbGluZXMgdGhhdCBpcyBhIG11bHRpcGxlIG9mIG1heC53aW5kb3dzLnNpemUgPSBudW1iZXIgb2Ygbm9uLWVtb3Rpb24gY2h1bmtzDQogIA0KICBuIDwtIG5yb3coZGF0YS5rZXB0KQ0KICBkYXRhLmtlcHQgPC0gZGF0YS5rZXB0W2MoMToobi0obiUlbWF4LndpbmRvdy5zaXplKSkpLF0NCiAgDQogIGxlbmd0aChkYXRhLmtlcHQkcGFydGljaXBhbnQpDQogIA0KICANCiAgcmVzdWx0cyA8LSBjKCkNCiAgZm9yIChwcm9jZXNzIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKQ0KICAgIHsNCiAgICByZXN1bHRzIDwtIGMocmVzdWx0cywgc3VtKGRhdGEua2VwdCRjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcz09cHJvY2VzcykpDQogICAgfQ0KICANCiAgbm9uLmNvbmZ1c2VkLnRhYmxlLnAxWyxwYXN0ZTAoc3Vic3RyKHAsIDEsIDUpLCIxIildIDwtIHJlc3VsdHMvKGxlbmd0aChkYXRhLmtlcHQkY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpJS8lbWF4LndpbmRvdy5zaXplKQ0KICByZXN1bHRzIDwtIGMoKQ0KICANCn0NCg0Kbm9uLmNvbmZ1c2VkLnRhYmxlLnAxDQoNCm5vbi5jb25mdXNlZC50YWJsZSA8LSBjYmluZChub24uY29uZnVzZWQudGFibGUucDEsIG5vbi5jb25mdXNlZC50YWJsZS5wMikNCm5vbi5jb25mdXNlZC50YWJsZQ0KYGBgDQoNCiMjIFJhbmRvbWl6YXRpb24gdGVzdHMNCg0KYGBge3J9DQpudW1iZXJfb2ZfcGVybXV0YXRpb25zID0gOTk5OQ0KDQpuIDwtIG1hdHJpeChkYXRhPU5BLG5yb3c9bGVuZ3RoKGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSxuY29sPTApDQplbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb24gPC0gZGF0YS5mcmFtZShuKQ0Kcm93bmFtZXMoZW1vdGlvbnMucmVzdWx0cy5wZXJtdXRhdGlvbi5jb3JyZWN0aW9uKSA8LSBjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcw0KYGBgDQoNCiMjIyBJbnRlcmVzdGVkDQoNCmBgYHtyfQ0KcmVzdWx0cyA8LSBjKCkNCm1lYW4ubm8uZW1vdGlvbiA8LSBjKCkNCm1lYW4uZW1vdGlvbiA8LSBjKCkNCnNkLm5vLmVtb3Rpb24gPC0gYygpDQpzZC5lbW90aW9uIDwtIGMoKQ0KDQpmb3IgKHByb2Nlc3MgaW4gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpIHsNCg0KICBvYnNlcnZlZC5tZWFuLmRpZmZlcmVuY2UgPC0gbWVhbihhcy5udW1lcmljKGludGVyZXN0ZWQudGFibGVbcHJvY2VzcyxdKSkgLSBtZWFuKGFzLm51bWVyaWMobm9uLmludGVyZXN0ZWQudGFibGVbcHJvY2VzcyxdKSkNCiAgb2JzZXJ2ZWQubWVhbi5kaWZmZXJlbmNlDQogIA0KICByYW5kb20ubWVhbi5kaWZmZXJlbmNlcyA8LSBjKG9ic2VydmVkLm1lYW4uZGlmZmVyZW5jZSkNCiAgDQogIHdob2xlLnNhbXBsZSA8LSBjKGFzLm51bWVyaWMoaW50ZXJlc3RlZC50YWJsZVtwcm9jZXNzLF0pLGFzLm51bWVyaWMobm9uLmludGVyZXN0ZWQudGFibGVbcHJvY2VzcyxdKSkgI3B1dCB0b2dldGhlciB0aGUgdHdvIHNhbXBsZXMNCiAgDQogIGZvciAoaSBpbiAxOm51bWJlcl9vZl9wZXJtdXRhdGlvbnMpIHsNCiAgICANCiAgICByYW5kb20uc2FtcGxlIDwtIHNhbXBsZSh3aG9sZS5zYW1wbGUpICNyYW5kb21pemUgdGhlIHNhbXBsZQ0KICAgIHJhbmRvbS50cmVhdG1lbnQuc2FtcGxlIDwtIHJhbmRvbS5zYW1wbGVbMTpsZW5ndGgoYXMubnVtZXJpYyhpbnRlcmVzdGVkLnRhYmxlW3Byb2Nlc3MsXSkpXSAjc2VsZWN0IG5ldyB0cmVhdG1lbnQgc2FtcGxlDQogICAgcmFuZG9tLmNvbnRyb2wuc2FtcGxlIDwtIHJhbmRvbS5zYW1wbGVbKDErbGVuZ3RoKGFzLm51bWVyaWMoaW50ZXJlc3RlZC50YWJsZVtwcm9jZXNzLF0pKSk6bGVuZ3RoKHJhbmRvbS5zYW1wbGUpXSAjc2VsZWN0IG5ldyBjb250cm9sIHNhbXBsZQ0KICAgIHJhbmRvbS5tZWFuLmRpZmZlcmVuY2VzIDwtIGMocmFuZG9tLm1lYW4uZGlmZmVyZW5jZXMsbWVhbihyYW5kb20udHJlYXRtZW50LnNhbXBsZSktbWVhbihyYW5kb20uY29udHJvbC5zYW1wbGUpKQ0KICANCiAgfQ0KICANCiAgICByZXN1bHRzIDwtIGMocmVzdWx0cywgc3VtKGFicyhyYW5kb20ubWVhbi5kaWZmZXJlbmNlcykgPj0gYWJzKG9ic2VydmVkLm1lYW4uZGlmZmVyZW5jZSkpIC8gbGVuZ3RoKHJhbmRvbS5tZWFuLmRpZmZlcmVuY2VzKSkNCiAgICBtZWFuLm5vLmVtb3Rpb24gPC0gYyhtZWFuLm5vLmVtb3Rpb24sbWVhbihhcy5udW1lcmljKG5vbi5pbnRlcmVzdGVkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgIG1lYW4uZW1vdGlvbiA8LSBjKG1lYW4uZW1vdGlvbixtZWFuKGFzLm51bWVyaWMoaW50ZXJlc3RlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgICBzZC5uby5lbW90aW9uIDwtIGMoc2Qubm8uZW1vdGlvbixzZChhcy5udW1lcmljKG5vbi5pbnRlcmVzdGVkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgIHNkLmVtb3Rpb24gPC0gYyhzZC5lbW90aW9uLHNkKGFzLm51bWVyaWMoaW50ZXJlc3RlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgICANCiAgICAjZ3JhcGhzDQogICAgaGlzdChyYW5kb20ubWVhbi5kaWZmZXJlbmNlcywgbWFpbiA9IHBhc3RlMCgiU2FtcGxpbmcgZGlzdHJpYnV0aW9uICIscHJvY2VzcyksIHhsYWIgPSAiTWVhbiBkaWZmZXJlbmNlIiwgcHJvYiA9IEYsIGNvbCA9ICJkYXJrcmVkIikNCiAgICBhYmxpbmUodiA9IG9ic2VydmVkLm1lYW4uZGlmZmVyZW5jZSwgY29sID0gImJsdWUiLCBsd2QgPSAyKQ0KICAgIA0KfQ0KYGBgDQoNCg0KYGBge3J9DQplbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb24kaW50ZXJlc3RlZF9wLnZhbHVlIDwtIHAuYWRqdXN0KHJlc3VsdHMsIG1ldGhvZD0iQkgiKQ0KZW1vdGlvbnMucmVzdWx0cy5wZXJtdXRhdGlvbi5jb3JyZWN0aW9uJGludGVyZXN0ZWRfbWVhbi5uby5lbW90aW9uIDwtIG1lYW4ubm8uZW1vdGlvbg0KZW1vdGlvbnMucmVzdWx0cy5wZXJtdXRhdGlvbi5jb3JyZWN0aW9uJGludGVyZXN0ZWRfbWVhbi5lbW90aW9uIDwtIG1lYW4uZW1vdGlvbg0KZW1vdGlvbnMucmVzdWx0cy5wZXJtdXRhdGlvbi5jb3JyZWN0aW9uJGludGVyZXN0ZWRfc2Qubm8uZW1vdGlvbiA8LSBzZC5uby5lbW90aW9uDQplbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb24kaW50ZXJlc3RlZF9zZC5lbW90aW9uIDwtIHNkLmVtb3Rpb24NCg0KZW1vdGlvbnMucmVzdWx0cy5wZXJtdXRhdGlvbi5jb3JyZWN0aW9uWyxjKCJpbnRlcmVzdGVkX3AudmFsdWUiKSwgZHJvcD1GQUxTRV0NCmBgYA0KDQojIyMgRm9jdXNlZA0KDQpgYGB7cn0NCnJlc3VsdHMgPC0gYygpDQptZWFuLm5vLmVtb3Rpb24gPC0gYygpDQptZWFuLmVtb3Rpb24gPC0gYygpDQpzZC5uby5lbW90aW9uIDwtIGMoKQ0Kc2QuZW1vdGlvbiA8LSBjKCkNCg0KZm9yIChwcm9jZXNzIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSB7DQoNCiAgb2JzZXJ2ZWQubWVhbi5kaWZmZXJlbmNlIDwtIG1lYW4oYXMubnVtZXJpYyhmb2N1c2VkLnRhYmxlW3Byb2Nlc3MsXSkpIC0gbWVhbihhcy5udW1lcmljKG5vbi5mb2N1c2VkLnRhYmxlW3Byb2Nlc3MsXSkpDQogIG9ic2VydmVkLm1lYW4uZGlmZmVyZW5jZQ0KICANCiAgcmFuZG9tLm1lYW4uZGlmZmVyZW5jZXMgPC0gYyhvYnNlcnZlZC5tZWFuLmRpZmZlcmVuY2UpDQogIA0KICB3aG9sZS5zYW1wbGUgPC0gYyhhcy5udW1lcmljKGZvY3VzZWQudGFibGVbcHJvY2VzcyxdKSxhcy5udW1lcmljKG5vbi5mb2N1c2VkLnRhYmxlW3Byb2Nlc3MsXSkpICNwdXQgdG9nZXRoZXIgdGhlIHR3byBzYW1wbGVzDQogIA0KICBmb3IgKGkgaW4gMTpudW1iZXJfb2ZfcGVybXV0YXRpb25zKSB7DQogICAgDQogICAgcmFuZG9tLnNhbXBsZSA8LSBzYW1wbGUod2hvbGUuc2FtcGxlKSAjcmFuZG9taXplIHRoZSBzYW1wbGUNCiAgICANCiAgICByYW5kb20udHJlYXRtZW50LnNhbXBsZSA8LSByYW5kb20uc2FtcGxlWzE6bGVuZ3RoKGFzLm51bWVyaWMoZm9jdXNlZC50YWJsZVtwcm9jZXNzLF0pKV0gI3NlbGVjdCBuZXcgdHJlYXRtZW50IHNhbXBsZQ0KICAgIHJhbmRvbS5jb250cm9sLnNhbXBsZSA8LSByYW5kb20uc2FtcGxlWygxK2xlbmd0aChhcy5udW1lcmljKGZvY3VzZWQudGFibGVbcHJvY2VzcyxdKSkpOmxlbmd0aChyYW5kb20uc2FtcGxlKV0gI3NlbGVjdCBuZXcgY29udHJvbCBzYW1wbGUNCiAgICByYW5kb20ubWVhbi5kaWZmZXJlbmNlcyA8LSBjKHJhbmRvbS5tZWFuLmRpZmZlcmVuY2VzLG1lYW4ocmFuZG9tLnRyZWF0bWVudC5zYW1wbGUpLW1lYW4ocmFuZG9tLmNvbnRyb2wuc2FtcGxlKSkNCiAgDQogIH0NCiAgDQogICAgcmVzdWx0cyA8LSBjKHJlc3VsdHMsIHN1bShhYnMocmFuZG9tLm1lYW4uZGlmZmVyZW5jZXMpID49IGFicyhvYnNlcnZlZC5tZWFuLmRpZmZlcmVuY2UpKSAvIGxlbmd0aChyYW5kb20ubWVhbi5kaWZmZXJlbmNlcykpDQogICAgbWVhbi5uby5lbW90aW9uIDwtIGMobWVhbi5uby5lbW90aW9uLG1lYW4oYXMubnVtZXJpYyhub24uZm9jdXNlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgICBtZWFuLmVtb3Rpb24gPC0gYyhtZWFuLmVtb3Rpb24sbWVhbihhcy5udW1lcmljKGZvY3VzZWQudGFibGVbcHJvY2VzcyxdKSkpDQogICAgc2Qubm8uZW1vdGlvbiA8LSBjKHNkLm5vLmVtb3Rpb24sc2QoYXMubnVtZXJpYyhub24uZm9jdXNlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgICBzZC5lbW90aW9uIDwtIGMoc2QuZW1vdGlvbixzZChhcy5udW1lcmljKGZvY3VzZWQudGFibGVbcHJvY2VzcyxdKSkpDQogICAgDQogICAgI2dyYXBocw0KICAgIGhpc3QocmFuZG9tLm1lYW4uZGlmZmVyZW5jZXMsIG1haW4gPSBwYXN0ZTAoIlNhbXBsaW5nIGRpc3RyaWJ1dGlvbiAiLHByb2Nlc3MpLCB4bGFiID0gIk1lYW4gZGlmZmVyZW5jZSIsIHByb2IgPSBGLCBjb2wgPSAiZGFya3JlZCIpDQogICAgYWJsaW5lKHYgPSBvYnNlcnZlZC5tZWFuLmRpZmZlcmVuY2UsIGNvbCA9ICJibHVlIiwgbHdkID0gMikNCiAgICANCn0NCmBgYA0KDQoNCmBgYHtyfQ0KZW1vdGlvbnMucmVzdWx0cy5wZXJtdXRhdGlvbi5jb3JyZWN0aW9uJGZvY3VzZWRfcC52YWx1ZSA8LSBwLmFkanVzdChyZXN1bHRzLCBtZXRob2Q9IkJIIikNCmVtb3Rpb25zLnJlc3VsdHMucGVybXV0YXRpb24uY29ycmVjdGlvbiRmb2N1c2VkX21lYW4ubm8uZW1vdGlvbiA8LSBtZWFuLm5vLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMucGVybXV0YXRpb24uY29ycmVjdGlvbiRmb2N1c2VkX21lYW4uZW1vdGlvbiA8LSBtZWFuLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMucGVybXV0YXRpb24uY29ycmVjdGlvbiRmb2N1c2VkX3NkLm5vLmVtb3Rpb24gPC0gc2Qubm8uZW1vdGlvbg0KZW1vdGlvbnMucmVzdWx0cy5wZXJtdXRhdGlvbi5jb3JyZWN0aW9uJGZvY3VzZWRfc2QuZW1vdGlvbiA8LSBzZC5lbW90aW9uDQoNCmVtb3Rpb25zLnJlc3VsdHMucGVybXV0YXRpb24uY29ycmVjdGlvblssYygiZm9jdXNlZF9wLnZhbHVlIiksIGRyb3A9RkFMU0VdDQpgYGANCg0KIyMjIERlbGlnaHRlZA0KDQpgYGB7cn0NCnJlc3VsdHMgPC0gYygpDQptZWFuLm5vLmVtb3Rpb24gPC0gYygpDQptZWFuLmVtb3Rpb24gPC0gYygpDQpzZC5uby5lbW90aW9uIDwtIGMoKQ0Kc2QuZW1vdGlvbiA8LSBjKCkNCg0KZm9yIChwcm9jZXNzIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSB7DQoNCiAgb2JzZXJ2ZWQubWVhbi5kaWZmZXJlbmNlIDwtIG1lYW4oYXMubnVtZXJpYyhkZWxpZ2h0ZWQudGFibGVbcHJvY2VzcyxdKSkgLSBtZWFuKGFzLm51bWVyaWMobm9uLmRlbGlnaHRlZC50YWJsZVtwcm9jZXNzLF0pKQ0KICBvYnNlcnZlZC5tZWFuLmRpZmZlcmVuY2UNCiAgDQogIHJhbmRvbS5tZWFuLmRpZmZlcmVuY2VzIDwtIGMob2JzZXJ2ZWQubWVhbi5kaWZmZXJlbmNlKQ0KICANCiAgd2hvbGUuc2FtcGxlIDwtIGMoYXMubnVtZXJpYyhkZWxpZ2h0ZWQudGFibGVbcHJvY2VzcyxdKSxhcy5udW1lcmljKG5vbi5kZWxpZ2h0ZWQudGFibGVbcHJvY2VzcyxdKSkgI3B1dCB0b2dldGhlciB0aGUgdHdvIHNhbXBsZXMNCiAgDQogIGZvciAoaSBpbiAxOm51bWJlcl9vZl9wZXJtdXRhdGlvbnMpIHsNCiAgICANCiAgICByYW5kb20uc2FtcGxlIDwtIHNhbXBsZSh3aG9sZS5zYW1wbGUpICNyYW5kb21pemUgdGhlIHNhbXBsZQ0KICAgIHJhbmRvbS50cmVhdG1lbnQuc2FtcGxlIDwtIHJhbmRvbS5zYW1wbGVbMTpsZW5ndGgoYXMubnVtZXJpYyhkZWxpZ2h0ZWQudGFibGVbcHJvY2VzcyxdKSldICNzZWxlY3QgbmV3IHRyZWF0bWVudCBzYW1wbGUNCiAgICByYW5kb20uY29udHJvbC5zYW1wbGUgPC0gcmFuZG9tLnNhbXBsZVsoMStsZW5ndGgoYXMubnVtZXJpYyhkZWxpZ2h0ZWQudGFibGVbcHJvY2VzcyxdKSkpOmxlbmd0aChyYW5kb20uc2FtcGxlKV0gI3NlbGVjdCBuZXcgY29udHJvbCBzYW1wbGUNCiAgICByYW5kb20ubWVhbi5kaWZmZXJlbmNlcyA8LSBjKHJhbmRvbS5tZWFuLmRpZmZlcmVuY2VzLG1lYW4ocmFuZG9tLnRyZWF0bWVudC5zYW1wbGUpLW1lYW4ocmFuZG9tLmNvbnRyb2wuc2FtcGxlKSkNCiAgDQogIH0NCiAgDQogICAgcmVzdWx0cyA8LSBjKHJlc3VsdHMsIHN1bShhYnMocmFuZG9tLm1lYW4uZGlmZmVyZW5jZXMpID49IGFicyhvYnNlcnZlZC5tZWFuLmRpZmZlcmVuY2UpKSAvIGxlbmd0aChyYW5kb20ubWVhbi5kaWZmZXJlbmNlcykpDQogICAgbWVhbi5uby5lbW90aW9uIDwtIGMobWVhbi5uby5lbW90aW9uLG1lYW4oYXMubnVtZXJpYyhub24uZGVsaWdodGVkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgIG1lYW4uZW1vdGlvbiA8LSBjKG1lYW4uZW1vdGlvbixtZWFuKGFzLm51bWVyaWMoZGVsaWdodGVkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgIHNkLm5vLmVtb3Rpb24gPC0gYyhzZC5uby5lbW90aW9uLHNkKGFzLm51bWVyaWMobm9uLmRlbGlnaHRlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgICBzZC5lbW90aW9uIDwtIGMoc2QuZW1vdGlvbixzZChhcy5udW1lcmljKGRlbGlnaHRlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgICANCiAgICAjZ3JhcGhzDQogICAgaGlzdChyYW5kb20ubWVhbi5kaWZmZXJlbmNlcywgbWFpbiA9IHBhc3RlMCgiU2FtcGxpbmcgZGlzdHJpYnV0aW9uICIscHJvY2VzcyksIHhsYWIgPSAiTWVhbiBkaWZmZXJlbmNlIiwgcHJvYiA9IEYsIGNvbCA9ICJkYXJrcmVkIikNCiAgICBhYmxpbmUodiA9IG9ic2VydmVkLm1lYW4uZGlmZmVyZW5jZSwgY29sID0gImJsdWUiLCBsd2QgPSAyKQ0KICAgIA0KfQ0KYGBgDQoNCg0KYGBge3J9DQplbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb24kZGVsaWdodGVkX3AudmFsdWUgPC0gcC5hZGp1c3QocmVzdWx0cywgbWV0aG9kPSJCSCIpDQplbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb24kZGVsaWdodGVkX21lYW4ubm8uZW1vdGlvbiA8LSBtZWFuLm5vLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMucGVybXV0YXRpb24uY29ycmVjdGlvbiRkZWxpZ2h0ZWRfbWVhbi5lbW90aW9uIDwtIG1lYW4uZW1vdGlvbg0KZW1vdGlvbnMucmVzdWx0cy5wZXJtdXRhdGlvbi5jb3JyZWN0aW9uJGRlbGlnaHRlZF9zZC5uby5lbW90aW9uIDwtIHNkLm5vLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMucGVybXV0YXRpb24uY29ycmVjdGlvbiRkZWxpZ2h0ZWRfc2QuZW1vdGlvbiA8LSBzZC5lbW90aW9uDQoNCmVtb3Rpb25zLnJlc3VsdHMucGVybXV0YXRpb24uY29ycmVjdGlvblssYygiZGVsaWdodGVkX3AudmFsdWUiKSwgZHJvcD1GQUxTRV0NCmBgYA0KDQojIyMgU2F0aXNmaWVkDQpgYGB7cn0NCnJlc3VsdHMgPC0gYygpDQptZWFuLm5vLmVtb3Rpb24gPC0gYygpDQptZWFuLmVtb3Rpb24gPC0gYygpDQpzZC5uby5lbW90aW9uIDwtIGMoKQ0Kc2QuZW1vdGlvbiA8LSBjKCkNCg0KZm9yIChwcm9jZXNzIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSB7DQoNCiAgb2JzZXJ2ZWQubWVhbi5kaWZmZXJlbmNlIDwtIG1lYW4oYXMubnVtZXJpYyhzYXRpc2ZpZWQudGFibGVbcHJvY2VzcyxdKSkgLSBtZWFuKGFzLm51bWVyaWMobm9uLnNhdGlzZmllZC50YWJsZVtwcm9jZXNzLF0pKQ0KICBvYnNlcnZlZC5tZWFuLmRpZmZlcmVuY2UNCiAgDQogIHJhbmRvbS5tZWFuLmRpZmZlcmVuY2VzIDwtIGMob2JzZXJ2ZWQubWVhbi5kaWZmZXJlbmNlKQ0KICANCiAgd2hvbGUuc2FtcGxlIDwtIGMoYXMubnVtZXJpYyhzYXRpc2ZpZWQudGFibGVbcHJvY2VzcyxdKSxhcy5udW1lcmljKG5vbi5zYXRpc2ZpZWQudGFibGVbcHJvY2VzcyxdKSkgI3B1dCB0b2dldGhlciB0aGUgdHdvIHNhbXBsZXMNCiAgDQogIGZvciAoaSBpbiAxOm51bWJlcl9vZl9wZXJtdXRhdGlvbnMpIHsNCiAgICANCiAgICByYW5kb20uc2FtcGxlIDwtIHNhbXBsZSh3aG9sZS5zYW1wbGUpICNyYW5kb21pemUgdGhlIHNhbXBsZQ0KICAgIHJhbmRvbS50cmVhdG1lbnQuc2FtcGxlIDwtIHJhbmRvbS5zYW1wbGVbMTpsZW5ndGgoYXMubnVtZXJpYyhzYXRpc2ZpZWQudGFibGVbcHJvY2VzcyxdKSldICNzZWxlY3QgbmV3IHRyZWF0bWVudCBzYW1wbGUNCiAgICByYW5kb20uY29udHJvbC5zYW1wbGUgPC0gcmFuZG9tLnNhbXBsZVsoMStsZW5ndGgoYXMubnVtZXJpYyhzYXRpc2ZpZWQudGFibGVbcHJvY2VzcyxdKSkpOmxlbmd0aChyYW5kb20uc2FtcGxlKV0gI3NlbGVjdCBuZXcgY29udHJvbCBzYW1wbGUNCiAgICByYW5kb20ubWVhbi5kaWZmZXJlbmNlcyA8LSBjKHJhbmRvbS5tZWFuLmRpZmZlcmVuY2VzLG1lYW4ocmFuZG9tLnRyZWF0bWVudC5zYW1wbGUpLW1lYW4ocmFuZG9tLmNvbnRyb2wuc2FtcGxlKSkNCiAgDQogIH0NCiAgDQogICAgcmVzdWx0cyA8LSBjKHJlc3VsdHMsIHN1bShhYnMocmFuZG9tLm1lYW4uZGlmZmVyZW5jZXMpID49IGFicyhvYnNlcnZlZC5tZWFuLmRpZmZlcmVuY2UpKSAvIGxlbmd0aChyYW5kb20ubWVhbi5kaWZmZXJlbmNlcykpDQogICAgbWVhbi5uby5lbW90aW9uIDwtIGMobWVhbi5uby5lbW90aW9uLG1lYW4oYXMubnVtZXJpYyhub24uc2F0aXNmaWVkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgIG1lYW4uZW1vdGlvbiA8LSBjKG1lYW4uZW1vdGlvbixtZWFuKGFzLm51bWVyaWMoc2F0aXNmaWVkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgIHNkLm5vLmVtb3Rpb24gPC0gYyhzZC5uby5lbW90aW9uLHNkKGFzLm51bWVyaWMobm9uLnNhdGlzZmllZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgICBzZC5lbW90aW9uIDwtIGMoc2QuZW1vdGlvbixzZChhcy5udW1lcmljKHNhdGlzZmllZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgICANCiAgICAjZ3JhcGhzDQogICAgaGlzdChyYW5kb20ubWVhbi5kaWZmZXJlbmNlcywgbWFpbiA9IHBhc3RlMCgiU2FtcGxpbmcgZGlzdHJpYnV0aW9uICIscHJvY2VzcyksIHhsYWIgPSAiTWVhbiBkaWZmZXJlbmNlIiwgcHJvYiA9IEYsIGNvbCA9ICJkYXJrcmVkIikNCiAgICBhYmxpbmUodiA9IG9ic2VydmVkLm1lYW4uZGlmZmVyZW5jZSwgY29sID0gImJsdWUiLCBsd2QgPSAyKQ0KICAgIA0KfQ0KYGBgDQoNCg0KYGBge3J9DQplbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb24kc2F0aXNmaWVkX3AudmFsdWUgPC0gcC5hZGp1c3QocmVzdWx0cywgbWV0aG9kPSJCSCIpDQplbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb24kc2F0aXNmaWVkX21lYW4ubm8uZW1vdGlvbiA8LSBtZWFuLm5vLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMucGVybXV0YXRpb24uY29ycmVjdGlvbiRzYXRpc2ZpZWRfbWVhbi5lbW90aW9uIDwtIG1lYW4uZW1vdGlvbg0KZW1vdGlvbnMucmVzdWx0cy5wZXJtdXRhdGlvbi5jb3JyZWN0aW9uJHNhdGlzZmllZF9zZC5uby5lbW90aW9uIDwtIHNkLm5vLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMucGVybXV0YXRpb24uY29ycmVjdGlvbiRzYXRpc2ZpZWRfc2QuZW1vdGlvbiA8LSBzZC5lbW90aW9uDQoNCmVtb3Rpb25zLnJlc3VsdHMucGVybXV0YXRpb24uY29ycmVjdGlvblssYygic2F0aXNmaWVkX3AudmFsdWUiKSwgZHJvcD1GQUxTRV0NCmBgYA0KDQojIyMgQW11c2VkDQpgYGB7cn0NCnJlc3VsdHMgPC0gYygpDQptZWFuLm5vLmVtb3Rpb24gPC0gYygpDQptZWFuLmVtb3Rpb24gPC0gYygpDQpzZC5uby5lbW90aW9uIDwtIGMoKQ0Kc2QuZW1vdGlvbiA8LSBjKCkNCg0KZm9yIChwcm9jZXNzIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKSB7DQoNCiAgb2JzZXJ2ZWQubWVhbi5kaWZmZXJlbmNlIDwtIG1lYW4oYXMubnVtZXJpYyhhbXVzZWQudGFibGVbcHJvY2VzcyxdKSkgLSBtZWFuKGFzLm51bWVyaWMobm9uLmFtdXNlZC50YWJsZVtwcm9jZXNzLF0pKQ0KICBvYnNlcnZlZC5tZWFuLmRpZmZlcmVuY2UNCiAgDQogIHJhbmRvbS5tZWFuLmRpZmZlcmVuY2VzIDwtIGMob2JzZXJ2ZWQubWVhbi5kaWZmZXJlbmNlKQ0KICANCiAgd2hvbGUuc2FtcGxlIDwtIGMoYXMubnVtZXJpYyhhbXVzZWQudGFibGVbcHJvY2VzcyxdKSxhcy5udW1lcmljKG5vbi5hbXVzZWQudGFibGVbcHJvY2VzcyxdKSkgI3B1dCB0b2dldGhlciB0aGUgdHdvIHNhbXBsZXMNCiAgDQogIGZvciAoaSBpbiAxOm51bWJlcl9vZl9wZXJtdXRhdGlvbnMpIHsNCiAgICANCiAgICByYW5kb20uc2FtcGxlIDwtIHNhbXBsZSh3aG9sZS5zYW1wbGUpICNyYW5kb21pemUgdGhlIHNhbXBsZQ0KICAgIHJhbmRvbS50cmVhdG1lbnQuc2FtcGxlIDwtIHJhbmRvbS5zYW1wbGVbMTpsZW5ndGgoYXMubnVtZXJpYyhhbXVzZWQudGFibGVbcHJvY2VzcyxdKSldICNzZWxlY3QgbmV3IHRyZWF0bWVudCBzYW1wbGUNCiAgICByYW5kb20uY29udHJvbC5zYW1wbGUgPC0gcmFuZG9tLnNhbXBsZVsoMStsZW5ndGgoYXMubnVtZXJpYyhhbXVzZWQudGFibGVbcHJvY2VzcyxdKSkpOmxlbmd0aChyYW5kb20uc2FtcGxlKV0gI3NlbGVjdCBuZXcgY29udHJvbCBzYW1wbGUNCiAgICByYW5kb20ubWVhbi5kaWZmZXJlbmNlcyA8LSBjKHJhbmRvbS5tZWFuLmRpZmZlcmVuY2VzLG1lYW4ocmFuZG9tLnRyZWF0bWVudC5zYW1wbGUpLW1lYW4ocmFuZG9tLmNvbnRyb2wuc2FtcGxlKSkNCiAgDQogIH0NCiAgDQogICAgcmVzdWx0cyA8LSBjKHJlc3VsdHMsIHN1bShhYnMocmFuZG9tLm1lYW4uZGlmZmVyZW5jZXMpID49IGFicyhvYnNlcnZlZC5tZWFuLmRpZmZlcmVuY2UpKSAvIGxlbmd0aChyYW5kb20ubWVhbi5kaWZmZXJlbmNlcykpDQogICAgbWVhbi5uby5lbW90aW9uIDwtIGMobWVhbi5uby5lbW90aW9uLG1lYW4oYXMubnVtZXJpYyhub24uYW11c2VkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgIG1lYW4uZW1vdGlvbiA8LSBjKG1lYW4uZW1vdGlvbixtZWFuKGFzLm51bWVyaWMoYW11c2VkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgIHNkLm5vLmVtb3Rpb24gPC0gYyhzZC5uby5lbW90aW9uLHNkKGFzLm51bWVyaWMobm9uLmFtdXNlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgICBzZC5lbW90aW9uIDwtIGMoc2QuZW1vdGlvbixzZChhcy5udW1lcmljKGFtdXNlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgICANCiAgICAjZ3JhcGhzDQogICAgaGlzdChyYW5kb20ubWVhbi5kaWZmZXJlbmNlcywgbWFpbiA9IHBhc3RlMCgiU2FtcGxpbmcgZGlzdHJpYnV0aW9uICIscHJvY2VzcyksIHhsYWIgPSAiTWVhbiBkaWZmZXJlbmNlIiwgcHJvYiA9IEYsIGNvbCA9ICJkYXJrcmVkIikNCiAgICBhYmxpbmUodiA9IG9ic2VydmVkLm1lYW4uZGlmZmVyZW5jZSwgY29sID0gImJsdWUiLCBsd2QgPSAyKQ0KICAgIA0KfQ0KYGBgDQoNCmBgYHtyfQ0KZW1vdGlvbnMucmVzdWx0cy5wZXJtdXRhdGlvbi5jb3JyZWN0aW9uJGFtdXNlZF9wLnZhbHVlIDwtIHAuYWRqdXN0KHJlc3VsdHMsIG1ldGhvZD0iQkgiKQ0KZW1vdGlvbnMucmVzdWx0cy5wZXJtdXRhdGlvbi5jb3JyZWN0aW9uJGFtdXNlZF9tZWFuLm5vLmVtb3Rpb24gPC0gbWVhbi5uby5lbW90aW9uDQplbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb24kYW11c2VkX21lYW4uZW1vdGlvbiA8LSBtZWFuLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMucGVybXV0YXRpb24uY29ycmVjdGlvbiRhbXVzZWRfc2Qubm8uZW1vdGlvbiA8LSBzZC5uby5lbW90aW9uDQplbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb24kYW11c2VkX3NkLmVtb3Rpb24gPC0gc2QuZW1vdGlvbg0KDQplbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb25bLGMoImFtdXNlZF9wLnZhbHVlIiksIGRyb3A9RkFMU0VdDQpgYGANCg0KIyMjIFJlbGF4ZWQNCg0KYGBge3J9DQpyZXN1bHRzIDwtIGMoKQ0KbWVhbi5uby5lbW90aW9uIDwtIGMoKQ0KbWVhbi5lbW90aW9uIDwtIGMoKQ0Kc2Qubm8uZW1vdGlvbiA8LSBjKCkNCnNkLmVtb3Rpb24gPC0gYygpDQoNCmZvciAocHJvY2VzcyBpbiBjb2xsYWJvcmF0aXZlLnByb2Nlc3Nlcykgew0KDQogIG9ic2VydmVkLm1lYW4uZGlmZmVyZW5jZSA8LSBtZWFuKGFzLm51bWVyaWMocmVsYXhlZC50YWJsZVtwcm9jZXNzLF0pKSAtIG1lYW4oYXMubnVtZXJpYyhub24ucmVsYXhlZC50YWJsZVtwcm9jZXNzLF0pKQ0KICBvYnNlcnZlZC5tZWFuLmRpZmZlcmVuY2UNCiAgDQogIHJhbmRvbS5tZWFuLmRpZmZlcmVuY2VzIDwtIGMob2JzZXJ2ZWQubWVhbi5kaWZmZXJlbmNlKQ0KICANCiAgd2hvbGUuc2FtcGxlIDwtIGMoYXMubnVtZXJpYyhyZWxheGVkLnRhYmxlW3Byb2Nlc3MsXSksYXMubnVtZXJpYyhub24ucmVsYXhlZC50YWJsZVtwcm9jZXNzLF0pKSAjcHV0IHRvZ2V0aGVyIHRoZSB0d28gc2FtcGxlcw0KICANCiAgZm9yIChpIGluIDE6bnVtYmVyX29mX3Blcm11dGF0aW9ucykgew0KICAgIA0KICAgIHJhbmRvbS5zYW1wbGUgPC0gc2FtcGxlKHdob2xlLnNhbXBsZSkgI3JhbmRvbWl6ZSB0aGUgc2FtcGxlDQogICAgcmFuZG9tLnRyZWF0bWVudC5zYW1wbGUgPC0gcmFuZG9tLnNhbXBsZVsxOmxlbmd0aChhcy5udW1lcmljKHJlbGF4ZWQudGFibGVbcHJvY2VzcyxdKSldICNzZWxlY3QgbmV3IHRyZWF0bWVudCBzYW1wbGUNCiAgICByYW5kb20uY29udHJvbC5zYW1wbGUgPC0gcmFuZG9tLnNhbXBsZVsoMStsZW5ndGgoYXMubnVtZXJpYyhyZWxheGVkLnRhYmxlW3Byb2Nlc3MsXSkpKTpsZW5ndGgocmFuZG9tLnNhbXBsZSldICNzZWxlY3QgbmV3IGNvbnRyb2wgc2FtcGxlDQogICAgcmFuZG9tLm1lYW4uZGlmZmVyZW5jZXMgPC0gYyhyYW5kb20ubWVhbi5kaWZmZXJlbmNlcyxtZWFuKHJhbmRvbS50cmVhdG1lbnQuc2FtcGxlKS1tZWFuKHJhbmRvbS5jb250cm9sLnNhbXBsZSkpDQogIA0KICB9DQogIA0KICAgIHJlc3VsdHMgPC0gYyhyZXN1bHRzLCBzdW0oYWJzKHJhbmRvbS5tZWFuLmRpZmZlcmVuY2VzKSA+PSBhYnMob2JzZXJ2ZWQubWVhbi5kaWZmZXJlbmNlKSkgLyBsZW5ndGgocmFuZG9tLm1lYW4uZGlmZmVyZW5jZXMpKQ0KICAgIG1lYW4ubm8uZW1vdGlvbiA8LSBjKG1lYW4ubm8uZW1vdGlvbixtZWFuKGFzLm51bWVyaWMobm9uLnJlbGF4ZWQudGFibGVbcHJvY2VzcyxdKSkpDQogICAgbWVhbi5lbW90aW9uIDwtIGMobWVhbi5lbW90aW9uLG1lYW4oYXMubnVtZXJpYyhyZWxheGVkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgIHNkLm5vLmVtb3Rpb24gPC0gYyhzZC5uby5lbW90aW9uLHNkKGFzLm51bWVyaWMobm9uLnJlbGF4ZWQudGFibGVbcHJvY2VzcyxdKSkpDQogICAgc2QuZW1vdGlvbiA8LSBjKHNkLmVtb3Rpb24sc2QoYXMubnVtZXJpYyhyZWxheGVkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgIA0KICAgICNncmFwaHMNCiAgICBoaXN0KHJhbmRvbS5tZWFuLmRpZmZlcmVuY2VzLCBtYWluID0gcGFzdGUwKCJTYW1wbGluZyBkaXN0cmlidXRpb24gIixwcm9jZXNzKSwgeGxhYiA9ICJNZWFuIGRpZmZlcmVuY2UiLCBwcm9iID0gRiwgY29sID0gImRhcmtyZWQiKQ0KICAgIGFibGluZSh2ID0gb2JzZXJ2ZWQubWVhbi5kaWZmZXJlbmNlLCBjb2wgPSAiYmx1ZSIsIGx3ZCA9IDIpDQogICAgDQp9DQpgYGANCg0KDQpgYGB7cn0NCmVtb3Rpb25zLnJlc3VsdHMucGVybXV0YXRpb24uY29ycmVjdGlvbiRyZWxheGVkX3AudmFsdWUgPC0gcC5hZGp1c3QocmVzdWx0cywgbWV0aG9kPSJCSCIpDQplbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb24kcmVsYXhlZF9tZWFuLm5vLmVtb3Rpb24gPC0gbWVhbi5uby5lbW90aW9uDQplbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb24kcmVsYXhlZF9tZWFuLmVtb3Rpb24gPC0gbWVhbi5lbW90aW9uDQplbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb24kcmVsYXhlZF9zZC5uby5lbW90aW9uIDwtIHNkLm5vLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMucGVybXV0YXRpb24uY29ycmVjdGlvbiRyZWxheGVkX3NkLmVtb3Rpb24gPC0gc2QuZW1vdGlvbg0KDQplbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb24kbWVhbi5kaWZmLnJlbGF4ZWQgPC0gKG1lYW4uZW1vdGlvbi1tZWFuLm5vLmVtb3Rpb24pDQplbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb24kbWVhbi5kaWZmLnJlbGF4ZWQNCg0KZW1vdGlvbnMucmVzdWx0cy5wZXJtdXRhdGlvbi5jb3JyZWN0aW9uWyxjKCJyZWxheGVkX3AudmFsdWUiLCJtZWFuLmRpZmYucmVsYXhlZCIpXQ0KYGBgDQoNCg0KIyMgV2lsY294b24gdGVzdHMgd2l0aCBCZW5qYW1pbmktSG9jaGJlcmcgY29ycmVjdGlvbg0KDQpgYGB7cn0NCm4gPC0gbWF0cml4KGRhdGE9TkEsbnJvdz1sZW5ndGgoY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpLG5jb2w9MCkNCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiA8LSBkYXRhLmZyYW1lKG4pDQpyb3duYW1lcyhlbW90aW9ucy5yZXN1bHRzLmJoLmNvcnJlY3Rpb24pIDwtIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzDQpgYGANCg0KIyMjIEludGVyZXN0ZWQNCmBgYHtyfQ0KcmVzdWx0cyA8LSBjKCkNCm1lYW4ubm8uZW1vdGlvbiA8LSBjKCkNCm1lYW4uZW1vdGlvbiA8LSBjKCkNCnNkLm5vLmVtb3Rpb24gPC0gYygpDQpzZC5lbW90aW9uIDwtIGMoKQ0KIGZvciAocHJvY2VzcyBpbiBjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcykNCiAgIHsNCiAgIA0KICAgcmVzdWx0cyA8LSBjKHJlc3VsdHMsIHdpbGNveC50ZXN0KHQoaW50ZXJlc3RlZC50YWJsZVtwcm9jZXNzLF0pLHQobm9uLmludGVyZXN0ZWQudGFibGVbcHJvY2VzcyxdKSkkcC52YWx1ZSkNCiAgIG1lYW4ubm8uZW1vdGlvbiA8LSBjKG1lYW4ubm8uZW1vdGlvbixtZWFuKGFzLm51bWVyaWMobm9uLmludGVyZXN0ZWQudGFibGVbcHJvY2VzcyxdKSkpDQogICBtZWFuLmVtb3Rpb24gPC0gYyhtZWFuLmVtb3Rpb24sbWVhbihhcy5udW1lcmljKGludGVyZXN0ZWQudGFibGVbcHJvY2VzcyxdKSkpDQogICBzZC5uby5lbW90aW9uIDwtIGMoc2Qubm8uZW1vdGlvbixzZChhcy5udW1lcmljKG5vbi5pbnRlcmVzdGVkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgc2QuZW1vdGlvbiA8LSBjKHNkLmVtb3Rpb24sc2QoYXMubnVtZXJpYyhpbnRlcmVzdGVkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICB9DQpgYGANCg0KYGBge3J9DQplbW90aW9ucy5yZXN1bHRzLmJoLmNvcnJlY3Rpb24kaW50ZXJlc3RlZF9wLnZhbHVlIDwtIHAuYWRqdXN0KHJlc3VsdHMsIG1ldGhvZD0iQkgiKQ0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uJGludGVyZXN0ZWRfbWVhbi5uby5lbW90aW9uIDwtIG1lYW4ubm8uZW1vdGlvbg0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uJGludGVyZXN0ZWRfbWVhbi5lbW90aW9uIDwtIG1lYW4uZW1vdGlvbg0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uJGludGVyZXN0ZWRfc2Qubm8uZW1vdGlvbiA8LSBzZC5uby5lbW90aW9uDQplbW90aW9ucy5yZXN1bHRzLmJoLmNvcnJlY3Rpb24kaW50ZXJlc3RlZF9zZC5lbW90aW9uIDwtIHNkLmVtb3Rpb24NCmBgYA0KDQojIyMgZm9jdXNlZA0KYGBge3J9DQpyZXN1bHRzIDwtIGMoKQ0KbWVhbi5uby5lbW90aW9uIDwtIGMoKQ0KbWVhbi5lbW90aW9uIDwtIGMoKQ0Kc2Qubm8uZW1vdGlvbiA8LSBjKCkNCnNkLmVtb3Rpb24gPC0gYygpDQogZm9yIChwcm9jZXNzIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKQ0KICAgew0KICAgDQogICByZXN1bHRzIDwtIGMocmVzdWx0cywgd2lsY294LnRlc3QodChmb2N1c2VkLnRhYmxlW3Byb2Nlc3MsXSksdChub24uZm9jdXNlZC50YWJsZVtwcm9jZXNzLF0pKSRwLnZhbHVlKQ0KICAgbWVhbi5uby5lbW90aW9uIDwtIGMobWVhbi5uby5lbW90aW9uLG1lYW4oYXMubnVtZXJpYyhub24uZm9jdXNlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgIG1lYW4uZW1vdGlvbiA8LSBjKG1lYW4uZW1vdGlvbixtZWFuKGFzLm51bWVyaWMoZm9jdXNlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgIHNkLm5vLmVtb3Rpb24gPC0gYyhzZC5uby5lbW90aW9uLHNkKGFzLm51bWVyaWMobm9uLmZvY3VzZWQudGFibGVbcHJvY2VzcyxdKSkpDQogICBzZC5lbW90aW9uIDwtIGMoc2QuZW1vdGlvbixzZChhcy5udW1lcmljKGZvY3VzZWQudGFibGVbcHJvY2VzcyxdKSkpDQogIH0NCmBgYA0KICANCmBgYHtyfQ0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uJGZvY3VzZWRfcC52YWx1ZSA8LSBwLmFkanVzdChyZXN1bHRzLCBtZXRob2Q9IkJIIikNCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiRmb2N1c2VkX21lYW4ubm8uZW1vdGlvbiA8LSBtZWFuLm5vLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiRmb2N1c2VkX21lYW4uZW1vdGlvbiA8LSBtZWFuLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiRmb2N1c2VkX3NkLm5vLmVtb3Rpb24gPC0gc2Qubm8uZW1vdGlvbg0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uJGZvY3VzZWRfc2QuZW1vdGlvbiA8LSBzZC5lbW90aW9uDQpgYGANCiMjIyBkZWxpZ2h0ZWQNCmBgYHtyfQ0KcmVzdWx0cyA8LSBjKCkNCm1lYW4ubm8uZW1vdGlvbiA8LSBjKCkNCm1lYW4uZW1vdGlvbiA8LSBjKCkNCnNkLm5vLmVtb3Rpb24gPC0gYygpDQpzZC5lbW90aW9uIDwtIGMoKQ0KIGZvciAocHJvY2VzcyBpbiBjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcykNCiAgIHsNCiAgIA0KICAgcmVzdWx0cyA8LSBjKHJlc3VsdHMsIHdpbGNveC50ZXN0KHQoZGVsaWdodGVkLnRhYmxlW3Byb2Nlc3MsXSksdChub24uZGVsaWdodGVkLnRhYmxlW3Byb2Nlc3MsXSkpJHAudmFsdWUpDQogICBtZWFuLm5vLmVtb3Rpb24gPC0gYyhtZWFuLm5vLmVtb3Rpb24sbWVhbihhcy5udW1lcmljKG5vbi5kZWxpZ2h0ZWQudGFibGVbcHJvY2VzcyxdKSkpDQogICBtZWFuLmVtb3Rpb24gPC0gYyhtZWFuLmVtb3Rpb24sbWVhbihhcy5udW1lcmljKGRlbGlnaHRlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgIHNkLm5vLmVtb3Rpb24gPC0gYyhzZC5uby5lbW90aW9uLHNkKGFzLm51bWVyaWMobm9uLmRlbGlnaHRlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgIHNkLmVtb3Rpb24gPC0gYyhzZC5lbW90aW9uLHNkKGFzLm51bWVyaWMoZGVsaWdodGVkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgDQogICANCiAgfQ0KYGBgDQoNCmBgYHtyfQ0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uJGRlbGlnaHRlZF9wLnZhbHVlIDwtIHAuYWRqdXN0KHJlc3VsdHMsIG1ldGhvZD0iQkgiKQ0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uJGRlbGlnaHRlZF9tZWFuLm5vLmVtb3Rpb24gPC0gbWVhbi5uby5lbW90aW9uDQplbW90aW9ucy5yZXN1bHRzLmJoLmNvcnJlY3Rpb24kZGVsaWdodGVkX21lYW4uZW1vdGlvbiA8LSBtZWFuLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiRkZWxpZ2h0ZWRfc2Qubm8uZW1vdGlvbiA8LSBzZC5uby5lbW90aW9uDQplbW90aW9ucy5yZXN1bHRzLmJoLmNvcnJlY3Rpb24kZGVsaWdodGVkX3NkLmVtb3Rpb24gPC0gc2QuZW1vdGlvbg0KYGBgDQojIyMgc2F0aXNmaWVkDQpgYGB7cn0NCnJlc3VsdHMgPC0gYygpDQptZWFuLm5vLmVtb3Rpb24gPC0gYygpDQptZWFuLmVtb3Rpb24gPC0gYygpDQpzZC5uby5lbW90aW9uIDwtIGMoKQ0Kc2QuZW1vdGlvbiA8LSBjKCkNCiBmb3IgKHByb2Nlc3MgaW4gY29sbGFib3JhdGl2ZS5wcm9jZXNzZXMpDQogICB7DQogICANCiAgIHJlc3VsdHMgPC0gYyhyZXN1bHRzLCB3aWxjb3gudGVzdCh0KHNhdGlzZmllZC50YWJsZVtwcm9jZXNzLF0pLHQobm9uLnNhdGlzZmllZC50YWJsZVtwcm9jZXNzLF0pKSRwLnZhbHVlKQ0KICAgbWVhbi5uby5lbW90aW9uIDwtIGMobWVhbi5uby5lbW90aW9uLG1lYW4oYXMubnVtZXJpYyhub24uc2F0aXNmaWVkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgbWVhbi5lbW90aW9uIDwtIGMobWVhbi5lbW90aW9uLG1lYW4oYXMubnVtZXJpYyhzYXRpc2ZpZWQudGFibGVbcHJvY2VzcyxdKSkpDQogICBzZC5uby5lbW90aW9uIDwtIGMoc2Qubm8uZW1vdGlvbixzZChhcy5udW1lcmljKG5vbi5zYXRpc2ZpZWQudGFibGVbcHJvY2VzcyxdKSkpDQogICBzZC5lbW90aW9uIDwtIGMoc2QuZW1vdGlvbixzZChhcy5udW1lcmljKHNhdGlzZmllZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgIA0KICB9DQpgYGANCg0KYGBge3J9DQplbW90aW9ucy5yZXN1bHRzLmJoLmNvcnJlY3Rpb24kc2F0aXNmaWVkX3AudmFsdWUgPC0gcC5hZGp1c3QocmVzdWx0cywgbWV0aG9kPSJCSCIpDQplbW90aW9ucy5yZXN1bHRzLmJoLmNvcnJlY3Rpb24kc2F0aXNmaWVkX21lYW4ubm8uZW1vdGlvbiA8LSBtZWFuLm5vLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiRzYXRpc2ZpZWRfbWVhbi5lbW90aW9uIDwtIG1lYW4uZW1vdGlvbg0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uJHNhdGlzZmllZF9zZC5uby5lbW90aW9uIDwtIHNkLm5vLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiRzYXRpc2ZpZWRfc2QuZW1vdGlvbiA8LSBzZC5lbW90aW9uDQpgYGANCiMjIyBhbXVzZWQNCmBgYHtyfQ0KcmVzdWx0cyA8LSBjKCkNCm1lYW4ubm8uZW1vdGlvbiA8LSBjKCkNCm1lYW4uZW1vdGlvbiA8LSBjKCkNCnNkLm5vLmVtb3Rpb24gPC0gYygpDQpzZC5lbW90aW9uIDwtIGMoKQ0KIGZvciAocHJvY2VzcyBpbiBjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcykNCiAgIHsNCiAgIA0KICAgcmVzdWx0cyA8LSBjKHJlc3VsdHMsIHdpbGNveC50ZXN0KHQoYW11c2VkLnRhYmxlW3Byb2Nlc3MsXSksdChub24uYW11c2VkLnRhYmxlW3Byb2Nlc3MsXSkpJHAudmFsdWUpDQogICBtZWFuLm5vLmVtb3Rpb24gPC0gYyhtZWFuLm5vLmVtb3Rpb24sbWVhbihhcy5udW1lcmljKG5vbi5hbXVzZWQudGFibGVbcHJvY2VzcyxdKSkpDQogICBtZWFuLmVtb3Rpb24gPC0gYyhtZWFuLmVtb3Rpb24sbWVhbihhcy5udW1lcmljKGFtdXNlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgIHNkLm5vLmVtb3Rpb24gPC0gYyhzZC5uby5lbW90aW9uLHNkKGFzLm51bWVyaWMobm9uLmFtdXNlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgIHNkLmVtb3Rpb24gPC0gYyhzZC5lbW90aW9uLHNkKGFzLm51bWVyaWMoYW11c2VkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgDQogIH0NCmBgYA0KDQpgYGB7cn0NCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiRhbXVzZWRfcC52YWx1ZSA8LSBwLmFkanVzdChyZXN1bHRzLCBtZXRob2Q9IkJIIikNCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiRhbXVzZWRfbWVhbi5uby5lbW90aW9uIDwtIG1lYW4ubm8uZW1vdGlvbg0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uJGFtdXNlZF9tZWFuLmVtb3Rpb24gPC0gbWVhbi5lbW90aW9uDQplbW90aW9ucy5yZXN1bHRzLmJoLmNvcnJlY3Rpb24kYW11c2VkX3NkLm5vLmVtb3Rpb24gPC0gc2Qubm8uZW1vdGlvbg0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uJGFtdXNlZF9zZC5lbW90aW9uIDwtIHNkLmVtb3Rpb24NCmBgYA0KIyMjIHJlbGF4ZWQNCmBgYHtyfQ0KcmVzdWx0cyA8LSBjKCkNCm1lYW4ubm8uZW1vdGlvbiA8LSBjKCkNCm1lYW4uZW1vdGlvbiA8LSBjKCkNCnNkLm5vLmVtb3Rpb24gPC0gYygpDQpzZC5lbW90aW9uIDwtIGMoKQ0KIGZvciAocHJvY2VzcyBpbiBjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcykNCiAgIHsNCiAgIA0KICAgcmVzdWx0cyA8LSBjKHJlc3VsdHMsIHdpbGNveC50ZXN0KHQocmVsYXhlZC50YWJsZVtwcm9jZXNzLF0pLHQobm9uLnJlbGF4ZWQudGFibGVbcHJvY2VzcyxdKSkkcC52YWx1ZSkNCiAgIG1lYW4ubm8uZW1vdGlvbiA8LSBjKG1lYW4ubm8uZW1vdGlvbixtZWFuKGFzLm51bWVyaWMobm9uLnJlbGF4ZWQudGFibGVbcHJvY2VzcyxdKSkpDQogICBtZWFuLmVtb3Rpb24gPC0gYyhtZWFuLmVtb3Rpb24sbWVhbihhcy5udW1lcmljKHJlbGF4ZWQudGFibGVbcHJvY2VzcyxdKSkpDQogICBzZC5uby5lbW90aW9uIDwtIGMoc2Qubm8uZW1vdGlvbixzZChhcy5udW1lcmljKG5vbi5yZWxheGVkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgc2QuZW1vdGlvbiA8LSBjKHNkLmVtb3Rpb24sc2QoYXMubnVtZXJpYyhyZWxheGVkLnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICAgDQogICANCiAgfQ0KYGBgDQoNCmBgYHtyfQ0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uJHJlbGF4ZWRfcC52YWx1ZSA8LSBwLmFkanVzdChyZXN1bHRzLCBtZXRob2Q9IkJIIikNCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiRyZWxheGVkX21lYW4ubm8uZW1vdGlvbiA8LSBtZWFuLm5vLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiRyZWxheGVkX21lYW4uZW1vdGlvbiA8LSBtZWFuLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiRyZWxheGVkX3NkLm5vLmVtb3Rpb24gPC0gc2Qubm8uZW1vdGlvbg0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uJHJlbGF4ZWRfc2QuZW1vdGlvbiA8LSBzZC5lbW90aW9uDQpgYGANCiMjIyBjb25maWRlbnQNCmBgYHtyfQ0KcmVzdWx0cyA8LSBjKCkNCm1lYW4ubm8uZW1vdGlvbiA8LSBjKCkNCm1lYW4uZW1vdGlvbiA8LSBjKCkNCnNkLm5vLmVtb3Rpb24gPC0gYygpDQpzZC5lbW90aW9uIDwtIGMoKQ0KIGZvciAocHJvY2VzcyBpbiBjb2xsYWJvcmF0aXZlLnByb2Nlc3NlcykNCiAgIHsNCiAgIA0KICAgcmVzdWx0cyA8LSBjKHJlc3VsdHMsIHdpbGNveC50ZXN0KHQoY29uZmlkZW50LnRhYmxlW3Byb2Nlc3MsXSksdChub24uY29uZmlkZW50LnRhYmxlW3Byb2Nlc3MsXSkpJHAudmFsdWUpDQogICBtZWFuLm5vLmVtb3Rpb24gPC0gYyhtZWFuLm5vLmVtb3Rpb24sbWVhbihhcy5udW1lcmljKG5vbi5jb25maWRlbnQudGFibGVbcHJvY2VzcyxdKSkpDQogICBtZWFuLmVtb3Rpb24gPC0gYyhtZWFuLmVtb3Rpb24sbWVhbihhcy5udW1lcmljKGNvbmZpZGVudC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgIHNkLm5vLmVtb3Rpb24gPC0gYyhzZC5uby5lbW90aW9uLHNkKGFzLm51bWVyaWMobm9uLmNvbmZpZGVudC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgIHNkLmVtb3Rpb24gPC0gYyhzZC5lbW90aW9uLHNkKGFzLm51bWVyaWMoY29uZmlkZW50LnRhYmxlW3Byb2Nlc3MsXSkpKQ0KICB9DQpgYGANCg0KYGBge3J9DQplbW90aW9ucy5yZXN1bHRzLmJoLmNvcnJlY3Rpb24kY29uZmlkZW50X3AudmFsdWUgPC0gcC5hZGp1c3QocmVzdWx0cywgbWV0aG9kPSJCSCIpDQplbW90aW9ucy5yZXN1bHRzLmJoLmNvcnJlY3Rpb24kY29uZmlkZW50X21lYW4ubm8uZW1vdGlvbiA8LSBtZWFuLm5vLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiRjb25maWRlbnRfbWVhbi5lbW90aW9uIDwtIG1lYW4uZW1vdGlvbg0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uJGNvbmZpZGVudF9zZC5uby5lbW90aW9uIDwtIHNkLm5vLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiRjb25maWRlbnRfc2QuZW1vdGlvbiA8LSBzZC5lbW90aW9uDQpgYGANCiMjIyBjb25mdXNlZA0KYGBge3J9DQpyZXN1bHRzIDwtIGMoKQ0KbWVhbi5uby5lbW90aW9uIDwtIGMoKQ0KbWVhbi5lbW90aW9uIDwtIGMoKQ0Kc2Qubm8uZW1vdGlvbiA8LSBjKCkNCnNkLmVtb3Rpb24gPC0gYygpDQogZm9yIChwcm9jZXNzIGluIGNvbGxhYm9yYXRpdmUucHJvY2Vzc2VzKQ0KICAgew0KICAgDQogICByZXN1bHRzIDwtIGMocmVzdWx0cywgd2lsY294LnRlc3QodChjb25mdXNlZC50YWJsZVtwcm9jZXNzLF0pLHQobm9uLmNvbmZ1c2VkLnRhYmxlW3Byb2Nlc3MsXSkpJHAudmFsdWUpDQogICBtZWFuLm5vLmVtb3Rpb24gPC0gYyhtZWFuLm5vLmVtb3Rpb24sbWVhbihhcy5udW1lcmljKG5vbi5jb25mdXNlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgIG1lYW4uZW1vdGlvbiA8LSBjKG1lYW4uZW1vdGlvbixtZWFuKGFzLm51bWVyaWMoY29uZnVzZWQudGFibGVbcHJvY2VzcyxdKSkpDQogICBzZC5uby5lbW90aW9uIDwtIGMoc2Qubm8uZW1vdGlvbixzZChhcy5udW1lcmljKG5vbi5jb25mdXNlZC50YWJsZVtwcm9jZXNzLF0pKSkNCiAgIHNkLmVtb3Rpb24gPC0gYyhzZC5lbW90aW9uLHNkKGFzLm51bWVyaWMoY29uZnVzZWQudGFibGVbcHJvY2VzcyxdKSkpDQogICANCiAgfQ0KYGBgDQoNCmBgYHtyfQ0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uJGNvbmZ1c2VkX3AudmFsdWUgPC0gcC5hZGp1c3QocmVzdWx0cywgbWV0aG9kPSJCSCIpDQplbW90aW9ucy5yZXN1bHRzLmJoLmNvcnJlY3Rpb24kY29uZnVzZWRfbWVhbi5uby5lbW90aW9uIDwtIG1lYW4ubm8uZW1vdGlvbg0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uJGNvbmZ1c2VkX21lYW4uZW1vdGlvbiA8LSBtZWFuLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiRjb25mdXNlZF9zZC5uby5lbW90aW9uIDwtIHNkLm5vLmVtb3Rpb24NCmVtb3Rpb25zLnJlc3VsdHMuYmguY29ycmVjdGlvbiRjb25mdXNlZF9zZC5lbW90aW9uIDwtIHNkLmVtb3Rpb24NCg0KZW1vdGlvbnMucmVzdWx0cy5iaC5jb3JyZWN0aW9uDQpgYGANCg0KIyMgRXhwb3J0DQoNCmBgYHtyfQ0KI0V4cG9ydGluZyByZXN1bHRzIGluIC54bHN4IGZpbGUNCg0Kd3JpdGUueGxzeChlbW90aW9ucy5yZXN1bHRzLnBlcm11dGF0aW9uLmNvcnJlY3Rpb24sIHBhc3RlMCgicmVzdWx0c19yZWNlaXZlcl9tZWFuaW5nZnVsX2FjdHMiLHRvU3RyaW5nKG1heC53aW5kb3cuc2l6ZSksIi54bHN4IikpIA0KYGBgDQoNCg0KDQo=